package weaver.fna.invoice.utils;


import com.engine.personalIncomeTax.biz.RecordsBiz;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.NTCredentials;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.params.ConnRouteParams;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;

import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import weaver.conn.RecordSet;
import weaver.fna.general.FnaCommon;
import weaver.fna.general.FnaLogSqlUtil;
import weaver.fna.invoice.Constants;
import weaver.fna.invoice.common.FnaAbstractInterface;
import weaver.fna.invoice.common.FnaInvoiceCommon;
import weaver.fna.invoice.sdk.SdkInvoiceUtil;
import weaver.general.BaseBean;
import weaver.general.GCONST;
import weaver.general.MD5;
import weaver.general.Util;
import weaver.hrm.HrmUserVarify;
import weaver.hrm.User;
import weaver.systeminfo.SystemEnv;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigInteger;
import java.net.Proxy;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
/**
 * @Author: lb2018
 * @Description:发票云工具类
 * @Date: 2020/6/9 10:45
 */
public class InvoiceCloudUtil {


    /**
     * 判断是否有生效的ocr接口、查验接口、发票云接口，并返回相关接口信息
     * @param user
     * @param queryOcr
     * @param queryCheck
     * @param queryCloud
     * @return
     */
    public static JSONObject getInterfaceInfo(User user,boolean queryOcr,boolean queryCheck,boolean queryCloud){
        JSONObject resultJson = new JSONObject();
        RecordSet rs = new RecordSet();
        if(queryOcr){
            boolean existEffectOcr=false;
            int imageCatalog = 0;
            String interfaceurl = "";
            String appKey = "";
            String secret = "";
            //如果有生效的未开启分部的ocr，直接使用
            rs.executeQuery("select * from fnainvoiceinterface where interfaceType=0 and status=1 and subIdStatus=0 ");
            if(rs.next()){
                imageCatalog = Util.getIntValue(rs.getString("imageCatalog"),0);
                interfaceurl = Util.null2String(rs.getString("interfaceurl"));
                appKey = Util.null2String(rs.getString("username"));
                secret = Util.null2String(rs.getString("password"));
                existEffectOcr = true;
            }
            if(!existEffectOcr){
                //查询当前人员所在分部的ocr接口
                rs.executeQuery("select * from fnainvoiceinterface where interfaceType=0 and status=1 and subIdStatus=1 ");
                while (rs.next()){
                    String subIds = Util.null2String(rs.getString("subIds"));
                    String[] subIds_split = subIds.split(",");
                    for(int i=0;i<subIds_split.length;i++){
                        if(subIds_split[i].equals(String.valueOf(user.getUserSubCompany1()))){
                            imageCatalog = Util.getIntValue(rs.getString("imageCatalog"),0);
                            interfaceurl = Util.null2String(rs.getString("interfaceurl"));
                            appKey = Util.null2String(rs.getString("username"));
                            secret = Util.null2String(rs.getString("password"));
                            existEffectOcr = true;
                            break;
                        }
                    }
                    if(existEffectOcr){
                        break;
                    }
                }
            }
            JSONObject ocrJson = new JSONObject();
            ocrJson.put("existEffectOcr",existEffectOcr);
            ocrJson.put("imageCatalog",imageCatalog);
            ocrJson.put("interfaceurl",interfaceurl);
            ocrJson.put("appKey",appKey);
            ocrJson.put("secret",secret);
            resultJson.put("ocr",ocrJson);
        }


        if(queryCheck){
            String tokenURL = "";
            String openIdURL = "";
            String verifyURL = "";
            String client_id = "";
            String client_secret = "";
            String Client = "";
            String GTAXID = "";
            //如果有生效的未开启分部的查验接口，直接使用
            boolean existEffectCheck=false;


            rs.executeQuery("select * from fnainvoiceinterface where interfaceType=1 and status=1 and subIdStatus=0 ");
            if(rs.next()){
                tokenURL = Util.null2String(rs.getString("tokenURL"));
                openIdURL = Util.null2String(rs.getString("openIdURL"));
                verifyURL = Util.null2String(rs.getString("interfaceurl"));
                client_id = Util.null2String(rs.getString("client_id"));
                client_secret = FnaInvoiceCommon.fnaDecrypt(Util.null2String(rs.getString("client_secret")));
                Client = Util.null2String(rs.getString("Client"));
                GTAXID = Util.null2String(rs.getString("GTAXID"));
                existEffectCheck = true;
            }
            if(!existEffectCheck){
                //查询当前人员所在分部的查验接口
                rs.executeQuery("select * from fnainvoiceinterface where interfaceType=1 and status=1 and subIdStatus=1 ");
                while (rs.next()){
                    String subIds = Util.null2String(rs.getString("subIds"));
                    String[] subIds_split = subIds.split(",");
                    for(int i=0;i<subIds_split.length;i++){
                        if(subIds_split[i].equals(String.valueOf(user.getUserSubCompany1()))){
                            tokenURL = Util.null2String(rs.getString("tokenURL"));
                            openIdURL = Util.null2String(rs.getString("openIdURL"));
                            verifyURL = Util.null2String(rs.getString("interfaceurl"));
                            client_id = Util.null2String(rs.getString("client_id"));
                            client_secret = FnaInvoiceCommon.fnaDecrypt(Util.null2String(rs.getString("client_secret")));
                            Client = Util.null2String(rs.getString("Client"));
                            GTAXID = Util.null2String(rs.getString("GTAXID"));
                            existEffectCheck = true;
                            break;
                        }
                    }
                    if(existEffectCheck){
                        break;
                    }
                }
            }

            JSONObject checkJson = new JSONObject();
            checkJson.put("existEffectCheck",existEffectCheck);
            checkJson.put("tokenURL",tokenURL);
            checkJson.put("openIdURL",openIdURL);
            checkJson.put("verifyURL",verifyURL);
            checkJson.put("client_id",client_id);
            checkJson.put("client_secret",client_secret);
            checkJson.put("Client",Client);
            checkJson.put("GTAXID",GTAXID);
            resultJson.put("check",checkJson);
        }


        if(queryCloud){
            boolean existEffectCloud=false;//是否存在生效的发票云接口
            String userName="";
            String password="";
            String cid="";
            String jsUrl="";
            String javaUrl="";
            String webUrl = "";
            int imageCatalog = 0;
            String aesKey="";
            //如果有生效的未开启分部的发票云接口，直接使用
            rs.executeQuery("select * from fnainvoiceinterface where interfaceType=2 and status=1 and subIdStatus=0 ");
            if(rs.next()){
                cid = Util.null2String(rs.getString("cid"));
                userName = Util.null2String(rs.getString("userName"));
                password = FnaInvoiceCommon.fnaDecrypt(Util.null2String(rs.getString("password")));
                jsUrl = Util.null2String(rs.getString("jsUrl"));
                javaUrl = Util.null2String(rs.getString("javaUrl"));
                webUrl = Util.null2String(rs.getString("webUrl"));
                imageCatalog = Util.getIntValue(rs.getString("imageCatalog"),0);
                aesKey = Util.null2String(rs.getString("aesKey"));
                existEffectCloud = true;
            }

            if(!existEffectCloud){
                //查询当前人员所在分部的发票云接口
                rs.executeQuery("select * from fnainvoiceinterface where interfaceType=2 and status=1 and subIdStatus=1 ");
                while (rs.next()){
                    String subIds = Util.null2String(rs.getString("subIds"));
                    String[] subIds_split = subIds.split(",");
                    for(int i=0;i<subIds_split.length;i++){
                        if(subIds_split[i].equals(String.valueOf(user.getUserSubCompany1()))){
                            cid = Util.null2String(rs.getString("cid"));
                            userName = Util.null2String(rs.getString("userName"));
                            password = FnaInvoiceCommon.fnaDecrypt(Util.null2String(rs.getString("password")));
                            jsUrl = Util.null2String(rs.getString("jsUrl"));
                            javaUrl = Util.null2String(rs.getString("javaUrl"));
                            webUrl = Util.null2String(rs.getString("webUrl"));
                            imageCatalog = Util.getIntValue(rs.getString("imageCatalog"),0);
                            aesKey = Util.null2String(rs.getString("aesKey"));
                            existEffectCloud = true;
                            break;
                        }
                    }
                    if(existEffectCloud){
                        break;
                    }
                }
            }

            JSONObject cloudJson = new JSONObject();
            cloudJson.put("existEffectCloud",existEffectCloud);
            cloudJson.put("userName",userName);
            cloudJson.put("password",password);
            cloudJson.put("cid",cid);
            cloudJson.put("imageCatalog",imageCatalog);
            cloudJson.put("jsUrl",jsUrl);
            cloudJson.put("webUrl",webUrl);
            JSONObject invoiceCloudUrl = getInvoiceCloudUrl();
            cloudJson.put("createCorpUrl",javaUrl+"/"+getString(invoiceCloudUrl,"createCorpUrl"));
            cloudJson.put("createAppUrl",javaUrl+"/"+getString(invoiceCloudUrl,"createAppUrl"));
            cloudJson.put("tokenUrl",javaUrl+"/"+getString(invoiceCloudUrl,"tokenUrl"));
            cloudJson.put("synInvoiceUrl",javaUrl+"/"+getString(invoiceCloudUrl,"synInvoiceUrl"));
            cloudJson.put("synBillingInfoUrl",javaUrl+"/"+getString(invoiceCloudUrl,"synBillingInfoUrl"));
            cloudJson.put("synDocUrl",javaUrl+"/"+getString(invoiceCloudUrl,"synDocUrl"));
            cloudJson.put("checkUrl",javaUrl+"/"+getString(invoiceCloudUrl,"checkUrl"));
            cloudJson.put("ocrUrl",javaUrl+"/"+getString(invoiceCloudUrl,"ocrUrl"));
            cloudJson.put("uploadFileUrl",javaUrl+"/"+getString(invoiceCloudUrl,"uploadFileUrl"));
            cloudJson.put("invoiceUsedNumberInfo",javaUrl+"/"+getString(invoiceCloudUrl,"invoiceUsedNumberInfo"));
            cloudJson.put("createAesKey",javaUrl+"/"+getString(invoiceCloudUrl,"createAesKey"));
            cloudJson.put("reimburseUrl",javaUrl+"/"+getString(invoiceCloudUrl,"reimburseUrl"));
            cloudJson.put("updateAppInfoUrl",javaUrl+"/"+getString(invoiceCloudUrl,"updateAppInfoUrl"));
            cloudJson.put("localCheckUrl",javaUrl+"/"+getString(invoiceCloudUrl,"localCheckUrl"));
            if("".equals(aesKey) && existEffectCloud){
                if("".equals(aesKey)){
                    JSONObject aesKeyJson = createAesKey(cloudJson.getString("createAesKey"), password, userName);
                    if(!aesKeyJson.getBoolean("flag")){
                        new BaseBean().writeLog("createAesKey失败"+aesKeyJson.getString("msg"));
                    }else{
                        JSONObject jsonData = aesKeyJson.getJSONObject("data");
                        aesKey = jsonData.getString("aesSecret");
                    }
                    rs.executeUpdate("update fnainvoiceinterface set aesKey=? where cid=?",aesKey,cid);
                }
            }
            cloudJson.put("aesKey",aesKey);
            resultJson.put("cloud",cloudJson);

        }

        return resultJson;
    }


    /**
     * 获取发票云接口域名后的地址后缀
     * @return
     */
    public static JSONObject getInvoiceCloudUrl(){
        RecordSet rs = new RecordSet();
        JSONObject jsonObject = new JSONObject();
        rs.executeQuery("select * from fnaInvoiceCloudUrl");
        while (rs.next()){
            String urlAddress = Util.null2String(rs.getString("urlAddress"));
            String sign = Util.null2String(rs.getString("sign"));
            jsonObject.put(sign,urlAddress);
        }
        return jsonObject;
    }

    /**
     * 获取发票相关权限，转为二进制
     * @param user
     * @return
     */
    public static int getInvoicePermissions(User user){
        int role=0;
        //微报账，发票接口接口配置，接口使用次数查询（包括接口使用查询和票据识别查询）,票据流程，发票去重校验设置，
        //邮件识别发票配置,票据项对应科目设置，连号发票报销控制,票据识别失败记录查询,
        //发票台账，企业台账,服务商设置，查验设置
        /*String permissionArray[]={"fnaMicroReport:setting","FnaInvoiceInterface:Set","FnaInvoiceUsedtimes:Query","FnaInvoiceReset:Permissions","FnainvoiceCheckControlLogic:Set",
        "FnaEmailInvoice:setting","FnaInvoiceSubject:Check","FnaSerialInvoiceControl:Set","FnaInvoiceFail:Check",
        "FnaInvoiceLedger:settings","FnaInvoiceLedger:settingsAll","fnaServiceprovider:Set","fnaInvoiceCheck:Set","fnaMicroReport:setting"};*/

        //使用权限：企业台账,我的票夹,接口使用次数查询,接口失败记录查询,
        // 识别查验记录查询,开票信息,发票云服务商设置,发票云查验设置,发票录入设置
        //预留权限 ：发票统计,报销设置
        //我的邮箱,勾选抵扣
        String permissionArray[]={"FnaInvoiceLedger:settingsAll","FnaInvoiceLedger:settings","FnaInvoiceUsedtimes:Query","FnaInvoiceFail:Check",
        "FnaInvoiceOcrCheck:Set","fnaMicroReport:setting","fnaServiceprovider:Set","fnaInvoiceCheck:Set","fnaMicroReport:setting",
        "fnaEmail:setting","fnaCheckDeduction:setting"};
        for(int i=0;i<permissionArray.length;i++){
            boolean permission =  HrmUserVarify.checkUserRight(permissionArray[i], user);
            if(permission){
                role = role+(int)Math.pow(2, i);
            }
        }
        return role;
    }
    /**
     * 获取发票云token，并回写至生效的发票云接口
     * @return
     */
    public static JSONObject getCloudToken(User user,String cid,String password,String userName,String tokenurl){
        JSONObject jsonObject  = new JSONObject();
        try{
            RecordSet rs = new RecordSet();



            //首先从表fnaInvoiceCloudToken中查询token,如果超过12小时，重新获取
            rs.executeQuery("select * from fnaInvoiceCloudToken where userId=?",user.getUID());
            if(rs.next()){
                String token = Util.null2String(rs.getString("token"));
                long currentTimeMillis = Long.valueOf(Util.null2String(rs.getString("currentTimeMillis")));
                long time = System.currentTimeMillis();
                if((time-currentTimeMillis)<1800000){//接口规定大于12小时 43200000,重新获取，  这块规定10小时重新获取，36000000，  30分钟获取一次1800000
                    jsonObject.put("flag",true);
                    jsonObject.put("token",token);
                    return jsonObject;
                }
            }

            //获取权限：
            int role = getInvoicePermissions(user);
            JSONObject param = new JSONObject();
            param.put("cid",cid);
            param.put("userId",user.getUID());
            param.put("name",user.getLastname());
            param.put("mobile",user.getMobile());
            param.put("role",role);
            String content = invoiceCloudEncode(param.toString(), password);
            Map<String, String> map = new HashMap<String, String>();
            map.put("appkey", userName);

            //插入日志表fnaInvoiceCloudLog
            String uuid = FnaCommon.getPrimaryKeyGuid1();
            rs.executeUpdate("insert into fnaInvoiceCloudLog(uuid,enterTime,requestType,description,interfaceurl,userName,password) values(?,?,?,?,?,?,?)",
                    uuid,Util.date(2),"OA发送请求","获取token",tokenurl,userName,password);
            FnaCommon.updateDbClobOrTextFieldValue("fnaInvoiceCloudLog", "param", param.toString(), "uuid", uuid, "string");
            FnaCommon.updateDbClobOrTextFieldValue("fnaInvoiceCloudLog", "md5Content",content, "uuid", uuid, "string");

            String token = postToUrl(tokenurl, content, map, "",uuid);

            //将token存入表中
            boolean existHistory=false;
            rs.executeQuery("select * from fnaInvoiceCloudToken where userId=?",user.getUID());
            if(rs.next()){
                existHistory = true;
            }

            String time = Util.null2String(System.currentTimeMillis());
            String updateTime = Util.date(2);
            if(existHistory){//update
                rs.executeUpdate("update fnaInvoiceCloudToken set cid=?,token=?,updateTime=?,currentTimeMillis=? where userId=?",
                        cid,token,updateTime,time,user.getUID());
            }else{//insert
                rs.executeUpdate("insert into fnaInvoiceCloudToken(cid,token,updateTime,currentTimeMillis,userId) values(?,?,?,?,?)",
                        cid,token,updateTime,time,user.getUID());
            }
            jsonObject.put("flag",true);
            jsonObject.put("token",token);
        }catch (Exception e){
            jsonObject.put("flag",false);
            jsonObject.put("msg",e.getMessage());
        }
        return jsonObject;
    }

    /**
     * 获取cid
     * @return
     */
    public static JSONObject getCloudCid(String interfaceurl,String account,String corpName,String userName,String password){
        JSONObject jsonObject = new JSONObject();
        try{
            JSONObject param = new JSONObject();
            param.put("account",account);
            param.put("corpName",corpName);
            String content = invoiceCloudEncode(param.toString(), password);
            Map<String, String> map = new HashMap<String, String>();
            map.put("appkey", userName);

            //插入日志表fnaInvoiceCloudLog
            RecordSet rs = new RecordSet();
            String uuid = FnaCommon.getPrimaryKeyGuid1();
            rs.executeUpdate("insert into fnaInvoiceCloudLog(uuid,enterTime,requestType,description,interfaceurl,userName,password) values(?,?,?,?,?,?,?)",
                    uuid,Util.date(2),"OA发送请求","获取CID",interfaceurl,userName,password);
            FnaCommon.updateDbClobOrTextFieldValue("fnaInvoiceCloudLog", "param", param.toString(), "uuid", uuid, "string");
            FnaCommon.updateDbClobOrTextFieldValue("fnaInvoiceCloudLog", "md5Content",content, "uuid", uuid, "string");

            String cid = postToUrl(interfaceurl, content, map, "",uuid);
            jsonObject.put("flag",true);
            jsonObject.put("cid",cid);
        }catch (Exception e){
            jsonObject.put("flag",false);
            jsonObject.put("msg",e.getMessage());
        }
        return jsonObject;
    }

    /**
     * 更新应用数据
     * @return
     */
    public static JSONObject updateAppInfo(String updateAppInfoUrl,String account,String oaUrl,String userName,String password){
        JSONObject jsonObject = new JSONObject();
        try{
            JSONObject param = new JSONObject();
            param.put("appName",account);
            param.put("thirdAddr",oaUrl);
            String content = invoiceCloudEncode(param.toString(), password);
            Map<String, String> map = new HashMap<String, String>();
            map.put("appkey", userName);

            //插入日志表fnaInvoiceCloudLog
            RecordSet rs = new RecordSet();
            String uuid = FnaCommon.getPrimaryKeyGuid1();
            rs.executeUpdate("insert into fnaInvoiceCloudLog(uuid,enterTime,requestType,description,interfaceurl,userName,password) values(?,?,?,?,?,?,?)",
                    uuid,Util.date(2),"OA发送请求","更新应用数据",updateAppInfoUrl,userName,password);
            FnaCommon.updateDbClobOrTextFieldValue("fnaInvoiceCloudLog", "param", param.toString(), "uuid", uuid, "string");
            FnaCommon.updateDbClobOrTextFieldValue("fnaInvoiceCloudLog", "md5Content",content, "uuid", uuid, "string");

            postToUrl(updateAppInfoUrl, content, map, "",uuid);
            jsonObject.put("flag",true);
        }catch (Exception e){
            jsonObject.put("flag",false);
            jsonObject.put("msg",e.getMessage());
        }
        return jsonObject;
    }

    /**
     * 创建应用，获取AppId 和 secret
     * @param interfaceurl
     * @param appName
     * @return
     */
    public static JSONObject CreateApp(String interfaceurl,String appName,String thirdAppId,String thirdAddr){
        JSONObject jsonObject = new JSONObject();
        try{
            JSONObject param = new JSONObject();
            param.put("appName",appName);
            param.put("appType",2);
            param.put("thirdAppId",thirdAppId);
            param.put("thirdAddr",thirdAddr);
            //插入日志表fnaInvoiceCloudLog
            RecordSet rs = new RecordSet();
            String uuid = FnaCommon.getPrimaryKeyGuid1();
            rs.executeUpdate("insert into fnaInvoiceCloudLog(uuid,enterTime,requestType,description,interfaceurl) values(?,?,?,?,?)",
                    uuid,Util.date(2),"OA发送请求","创建应用",interfaceurl);
            FnaCommon.updateDbClobOrTextFieldValue("fnaInvoiceCloudLog", "param", param.toString(), "uuid", uuid, "string");
            String data = postToUrl(interfaceurl, param.toString(), null, "",uuid);
            jsonObject.put("flag",true);
            jsonObject.put("data",data);
        }catch (Exception e){
            jsonObject.put("flag",false);
            jsonObject.put("msg",e.getMessage());
        }
        return jsonObject;
    }

    /**
     * 同步开票信息、同步发票信息
     * @param interfaceurl
     * @param param
     * @param userName
     * @param password
     * @return
     */
    public static JSONObject synBillingInfo(String interfaceurl,JSONObject param,String userName,String password){
        JSONObject jsonObject = new JSONObject();
        try{
            String content = invoiceCloudEncode(param.toString(), password);
            Map<String, String> map = new HashMap<String, String>();
            map.put("appkey", userName);

            //插入日志表fnaInvoiceCloudLog
            RecordSet rs = new RecordSet();
            String uuid = FnaCommon.getPrimaryKeyGuid1();
            rs.executeUpdate("insert into fnaInvoiceCloudLog(uuid,enterTime,requestType,description,interfaceurl,userName,password) values(?,?,?,?,?,?,?)",
                    uuid,Util.date(2),"OA发送请求","实时同步开票、发票信息",interfaceurl,userName,password);
            FnaCommon.updateDbClobOrTextFieldValue("fnaInvoiceCloudLog", "param", param.toString(), "uuid", uuid, "string");
            FnaCommon.updateDbClobOrTextFieldValue("fnaInvoiceCloudLog", "md5Content",content, "uuid", uuid, "string");

            String data = postToUrl(interfaceurl, content, map, "",uuid);
            jsonObject.put("flag",true);
            jsonObject.put("data",data);
        }catch (Exception e){
            jsonObject.put("flag",false);
            jsonObject.put("msg",e.getMessage());
        }
        return jsonObject;
    }

    /**
     * 推送目录id
     * @param synDocUrl
     * @param cid
     * @param secid
     * @param userName
     * @param password
     * @return
     */
    public static JSONObject pushSecid(String synDocUrl,String cid,String secid,String userName,String password,int userId){
        JSONObject jsonObject = new JSONObject();
        try{
            JSONObject param = new JSONObject();
            param.put("cid",cid);
            param.put("secid",secid);
            param.put("userId",userId);
            String content = invoiceCloudEncode(param.toString(), password);
            Map<String, String> map = new HashMap<String, String>();
            map.put("appkey", userName);

            //插入日志表fnaInvoiceCloudLog
            RecordSet rs = new RecordSet();
            String uuid = FnaCommon.getPrimaryKeyGuid1();
            rs.executeUpdate("insert into fnaInvoiceCloudLog(uuid,enterTime,requestType,description,interfaceurl,userName,password) values(?,?,?,?,?,?,?)",
                    uuid,Util.date(2),"OA发送请求","同步目录",synDocUrl,userName,password);
            FnaCommon.updateDbClobOrTextFieldValue("fnaInvoiceCloudLog", "param", param.toString(), "uuid", uuid, "string");
            FnaCommon.updateDbClobOrTextFieldValue("fnaInvoiceCloudLog", "md5Content",content, "uuid", uuid, "string");

            postToUrl(synDocUrl, content, map, "",uuid);
            jsonObject.put("flag",true);
        }catch (Exception e){
            jsonObject.put("flag",false);
            jsonObject.put("msg",e.getMessage());
        }
        return jsonObject;
    }


    /**
     * 获取json中的值
     * @param json
     * @param key
     * @return
     */
    public static String getString(JSONObject json, String  key){
        if(json.containsKey(key)){
            return json.getString(key);
        }else{
            return "";
        }
    }


    public static String postToUrl(String url, String content,Map<String, String> headers,String xmlEncoding,String uuid,String aesKey) throws Exception {
        return postToUrl(url,content,headers,xmlEncoding,uuid,"",null,aesKey);
    }
    public static String postToUrl(String url, String content,Map<String, String> headers,String xmlEncoding,String uuid) throws Exception {
        return postToUrl(url,content,headers,xmlEncoding,uuid,"",null,"");
    }
    /**
     *
     * @param url
     * @param content
     * @param headers
     * @param xmlEncoding
     * @return
     * @throws IOException
     */
    public static String postToUrl(String url, String content,Map<String, String> headers,String xmlEncoding,String uuid,String from,User user,String aesKey) throws Exception {
        String errorMsg="";

        String data="";
        if("".equals(xmlEncoding)){
            xmlEncoding = "UTF-8";
        }
        DefaultHttpClient httpclient = null;
        HttpPost httpPost = null;
        try {
            httpclient = new DefaultHttpClient();
            if(ProxyUtil.ifExistsProxy()){
                Map<String, String> proxyProperty = ProxyUtil.getProxyProperty();
                String proxyUrl = proxyProperty.getOrDefault("proxyUrl","");
                int proxyPort = Util.getIntValue(proxyProperty.getOrDefault("proxyPort",""),8080);
                String proxyUser = proxyProperty.getOrDefault("proxyUser","");
                String proxyPwd = proxyProperty.getOrDefault("proxyPwd","");

                if(!"".equals(proxyUser)&&!"".equals(proxyPwd)) {
                    httpclient.getCredentialsProvider().setCredentials(
                            new AuthScope(proxyUrl, proxyPort),
                            new UsernamePasswordCredentials(proxyUser, proxyPwd)
                    );
                }
                HttpHost proxy = new HttpHost(proxyUrl,proxyPort);
                httpclient.getParams().setParameter(ConnRouteParams.DEFAULT_PROXY,proxy);
            }

            httpPost = new HttpPost(url);
            JSONObject response = null;
            StringEntity s = new StringEntity(content, Charset.forName("UTF-8"));
            httpPost.addHeader("Content-type", "application/json; charset=utf-8");
            httpPost.addHeader("Accept", "application/json");

            //设置超时时间
            RequestConfig config = RequestConfig.custom().setConnectTimeout(130000) //连接超时时间
                        .setConnectionRequestTimeout(130000)
                        .setSocketTimeout(130000) //数据传输的超时时间
                        .setStaleConnectionCheckEnabled(true) //提交请求前测试连接是否可用
                        .build();



            httpPost.setConfig(config);
            httpPost.setEntity(s);

            if (null != headers) {
                for (Map.Entry<String, String> entry : headers.entrySet()) {
                    httpPost.addHeader(entry.getKey(), entry.getValue());
                }
            }
            HttpResponse res = httpclient.execute(httpPost);
            if (res.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                HttpEntity entity = res.getEntity();
                String result = Util.null2String(EntityUtils.toString(res.getEntity()));
                FnaCommon.updateDbClobOrTextFieldValue("fnaInvoiceCloudLog", "returnResult", result, "uuid", uuid, "string");
                if ("".equals(result)) {
                    throw new Exception("发票云接口返回空！");
                }
                try {
                    response = JSONObject.fromObject(result);
                } catch (Exception e) {
                    throw new Exception("发票云接口返参数json格式化异常！");
                }
                JSONObject actionMsg = response.getJSONObject("actionMsg");
                String code = actionMsg.getString("code");
                if ("0".equals(code)) {//创建成功
                    if (response.containsKey("data")) {
                        data = response.getString("data");

                        //新接口，需要解密
                        if (!"".equals(aesKey) && !"".equals(data)) {
                            data = InvoiceCloudAESUtil.decrypt(aesKey, data);
                            response.put("data", data);
                            FnaCommon.updateDbClobOrTextFieldValue("fnaInvoiceCloudLog", "returnResult", response.toString(), "uuid", uuid, "string");
                        }
                    }
                } else {
                    errorMsg = actionMsg.getString("message");
                    if ("check".equals(from)) {
                        new BaseBean().writeLog("checkException", errorMsg);
                        FnaInvoiceCommon.saveFailLog(user.getUID(), 1, errorMsg);
                    }
                    throw new Exception(errorMsg);
                }
            } else {
                FnaCommon.updateDbClobOrTextFieldValue("fnaInvoiceCloudLog", "returnResult", "请求失败HttpStatus=" + res.getStatusLine().getStatusCode(), "uuid", uuid, "string");
                throw new Exception("请求失败！");
            }
        }catch (Exception e){
            errorMsg = e.getMessage();
        }finally {
            if(httpclient!=null){
                httpclient.close();
            }
        }
        if(!"".equals(errorMsg)){
            throw new Exception(errorMsg);
        }
        return data;
    }

    /**
     * 发票云加密
     * @param content
     * @param secret
     * @return
     */
    public static  String invoiceCloudEncode(String content,String secret){
        long time = System.currentTimeMillis();
        content = content+"&time="+time;
        String md5Content = Md5Encode(content + "&secret=" + secret);
        content = content+"&md5="+md5Content;
        return content;
    }

    /**
     * 发票云加密
     * @param content
     * @param secret
     * @return
     */
    public static  String invoiceCloudEncode(String content,String secret,long time){
        content = content+"&time="+time;
        String md5Content = Md5Encode(content + "&secret=" + secret);
        return md5Content;
    }

    /**
     * md5加密
     * @param content
     * @return
     */
    public static String Md5Encode(String content){
        char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
        try {
            byte[] btInput = content.getBytes("UTF-8");
            // 获得MD5摘要算法的 MessageDigest 对象
            MessageDigest mdInst = MessageDigest.getInstance("MD5");
            // 使用指定的字节更新摘要
            mdInst.update(btInput);
            // 获得密文
            byte[] md = mdInst.digest();
            // 把密文转换成十六进制的字符串形式
            int j = md.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = md[i];
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(str);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 根据sql获取发票信息
     * @return
     */
    public static JSONArray getInvoiceInfos(String sql,int start_pos,int page_size){
        DecimalFormat df = new DecimalFormat("#############################0.00");
        JSONArray invoiceArray = new JSONArray();
        RecordSet rs = new RecordSet();
        RecordSet rs2 = new RecordSet();
        RecordSet rs3 = new RecordSet();
        RecordSet rs4 = new RecordSet();
        String fnainvoiceledger[] = {"id","billingDate","invoiceCode","invoiceNumber","invoiceType","seller","purchaser","invoiceServiceYype",
                "priceWithoutTax","taxRate","tax","taxIncludedPrice","authenticity","reimbursementDate","reimbursePerson","requestId","userid_new",
                "invoiceSource_new","checkcode","status","card_id_new","encrypt_code_new","openid_new","wechatstatus","imageID","purchaserTaxNo","salesTaxNo",
                "entryTime","company_seal","form_type","form_name","kind","category","imageDocId","checkStatus","updateOperate","cloudId","codeConfirm","numberConfirm","requestName",
                "receiptor","reviewer","issuer","province","city","travel_tax"};
        String fnainvoiceledgerdetail[]={"invoiceserviceyype","specification","unit","unitNumber2","originalUnitPrice","priceWithoutTax","taxRate","tax","startDate","endDate","numberPlate","type"};
        String fnaInvoiceLedgerDtl[]={"remark","checkCodeSix","sellerAddress","purchaserAddress","salesBank","purchaserBank"};
        String trainInvoice[]={"time","name","station_geton","station_getoff","train_number","seat"};
        String taxiInvoice[]={"time_geton","time_getoff","mileage","place"};
        String machineInvoice[]={"time","category","seller_tax_id","buyer_tax_id"};
        String tollInvoice[]={"time","entrance","export"};
        String carInvoice[]={"time","station_geton","station_getoff","name"};
        String second_carInvoice[]={"seller_id","buyer_id","company_name","company_tax_id","license_plate","registration_number","car_code","car_model"};
        String motor_VehicleInvoice[]={"machine_code","machine_number","pretax_amount","seller_tax_id","buyer_id","tax_authorities","tax_authorities_code",
        "car_code","car_engine_code","car_model","certificate_number"};
        String airInvoice[]={"user_name","user_id","agentcode","issue_by","fare","fuel_surcharge","caac_development_fund","insurance"};
        String airDtlInvoice[]={"from_city","to_city","flight_number","airdate","airtime","seat","carrier"};
        String smallInvoice[]={"storename","time","tips","currency_code","type","discount"};

        String fnaDidiInvoice[]={"startDate","endDate","phone"};
        String fnaDidiDtlInvoice[]={"carType","time_geton","city","station_geton","station_getoff","mileage","total"};
        String fnaBoatInvoice[]={"time","station_geton","station_getoff","name","currency_code"};

        //报销状况
        String fnaInvoiceReimbursement[]={"requestid","reimbursementAmt","userid","reimbursementDate","requestName"};

        int start=0;
        rs.executeQuery(sql);
        while (rs.next()){
            if(start>=start_pos && page_size>0 ) {
                JSONObject fnainvoiceledgerJo = new JSONObject();
                int id = Util.getIntValue(rs.getString("id"), 0);
                int invoiceType = Util.getIntValue(rs.getString("invoiceType"), 0);
                int requestId = Util.getIntValue(rs.getString("requestId"), 0);
                for (int i = 0; i < fnainvoiceledger.length; i++) {
                    String key = fnainvoiceledger[i];
                    if("requestName".equals(key)){
                        String requestName="";
                        if(requestId>0){
                            rs2.executeQuery("select  requestName from workflow_requestBase where requestId=?",requestId);
                            if(rs2.next()){
                                requestName = Util.null2String(rs2.getString("requestName"));
                            }
                        }
                        fnainvoiceledgerJo.put("requestName",requestName);
                    }else{
                        fnainvoiceledgerJo.put(key, Util.null2String(rs.getString(key)));
                    }

                }

                JSONArray fnainvoiceledgerdetailJa = new JSONArray();
                rs2.executeQuery("select * from fnainvoiceledgerdetail where mainid=?", id);
                while (rs2.next()) {
                    JSONObject fnainvoiceledgerdetailJo = new JSONObject();
                    for (int i = 0; i < fnainvoiceledgerdetail.length; i++) {
                        String key = fnainvoiceledgerdetail[i];
                        fnainvoiceledgerdetailJo.put(key, Util.null2String(rs2.getString(key)));
                    }
                    fnainvoiceledgerdetailJa.add(fnainvoiceledgerdetailJo);
                }
                fnainvoiceledgerJo.put("fnainvoiceledgerdetail", fnainvoiceledgerdetailJa);
                if (invoiceType == 1 || invoiceType == 2 || invoiceType == 15 || invoiceType == 16 || invoiceType == 12
                        || invoiceType == 3 || invoiceType == 17 || invoiceType == 19 || invoiceType == 20 || invoiceType == 21) {
                    rs3.executeQuery("select * from FnaInvoiceLedgerDtl where mainid=?", id);
                    if (rs3.next()) {
                        JSONObject FnaInvoiceLedgerDtlJo = new JSONObject();
                        for (int i = 0; i < fnaInvoiceLedgerDtl.length; i++) {
                            String key = fnaInvoiceLedgerDtl[i];
                            FnaInvoiceLedgerDtlJo.put(key, Util.null2String(rs3.getString(key)));
                        }
                        fnainvoiceledgerJo.put("fnaInvoiceLedgerDtl", FnaInvoiceLedgerDtlJo);
                    }
                }
                if (invoiceType == 8) {//火车票
                    rs3.executeQuery("select * from trainInvoice where mainid=?", id);
                    if (rs3.next()) {
                        JSONObject trainInvoiceJo = new JSONObject();
                        for (int i = 0; i < trainInvoice.length; i++) {
                            String key = trainInvoice[i];
                            trainInvoiceJo.put(key, Util.null2String(rs3.getString(key)));
                        }
                        fnainvoiceledgerJo.put("trainInvoice", trainInvoiceJo);
                    }
                } else if (invoiceType == 7) {//出租车发票
                    rs3.executeQuery("select * from taxiInvoice where mainid=?", id);
                    if (rs3.next()) {
                        JSONObject taxiInvoiceJo = new JSONObject();
                        for (int i = 0; i < taxiInvoice.length; i++) {
                            String key = taxiInvoice[i];
                            taxiInvoiceJo.put(key, Util.null2String(rs3.getString(key)));
                        }
                        fnainvoiceledgerJo.put("taxiInvoice", taxiInvoiceJo);
                    }
                } else if (invoiceType == 3) {//通用机打发票
                    rs3.executeQuery("select * from machineInvoice where mainid=?", id);
                    if (rs3.next()) {
                        JSONObject machineInvoiceJo = new JSONObject();
                        for (int i = 0; i < machineInvoice.length; i++) {
                            String key = machineInvoice[i];
                            machineInvoiceJo.put(key, Util.null2String(rs3.getString(key)));
                        }
                        fnainvoiceledgerJo.put("machineInvoice", machineInvoiceJo);
                    }
                } else if (invoiceType == 9) {//过路费发票表
                    rs3.executeQuery("select * from tollInvoice where mainid=?", id);
                    if (rs3.next()) {
                        JSONObject tollInvoiceJo = new JSONObject();
                        for (int i = 0; i < tollInvoice.length; i++) {
                            String key = tollInvoice[i];
                            tollInvoiceJo.put(key, Util.null2String(rs3.getString(key)));
                        }
                        fnainvoiceledgerJo.put("tollInvoice", tollInvoiceJo);
                    }
                } else if (invoiceType == 10) {//客运汽车发票
                    rs3.executeQuery("select * from carInvoice where mainid=?", id);
                    if (rs3.next()) {
                        JSONObject carInvoiceJo = new JSONObject();
                        for (int i = 0; i < carInvoice.length; i++) {
                            String key = carInvoice[i];
                            carInvoiceJo.put(key, Util.null2String(rs3.getString(key)));
                        }
                        fnainvoiceledgerJo.put("carInvoice", carInvoiceJo);
                    }
                } else if (invoiceType == 11) {//二手车销售统一发票表
                    rs3.executeQuery("select * from second_carInvoice where mainid=?", id);
                    if (rs3.next()) {
                        JSONObject second_carInvoiceJo = new JSONObject();
                        for (int i = 0; i < second_carInvoice.length; i++) {
                            String key = second_carInvoice[i];
                            second_carInvoiceJo.put(key, Util.null2String(rs3.getString(key)));
                        }
                        fnainvoiceledgerJo.put("second_carInvoice", second_carInvoiceJo);
                    }
                } else if (invoiceType == 12) {//机动车销售统一发票
                    rs3.executeQuery("select * from motor_VehicleInvoice where mainid=?", id);
                    if (rs3.next()) {
                        JSONObject motor_VehicleInvoiceJo = new JSONObject();
                        for (int i = 0; i < motor_VehicleInvoice.length; i++) {
                            String key = motor_VehicleInvoice[i];
                            motor_VehicleInvoiceJo.put(key, Util.null2String(rs3.getString(key)));
                        }
                        fnainvoiceledgerJo.put("motor_VehicleInvoice", motor_VehicleInvoiceJo);
                    }
                } else if (invoiceType == 14) {//航空运输电子客票行程单
                    rs3.executeQuery("select * from airInvoice where mainid=?", id);
                    if (rs3.next()) {
                        JSONObject airInvoiceJo = new JSONObject();
                        for (int i = 0; i < airInvoice.length; i++) {
                            String key = airInvoice[i];
                            airInvoiceJo.put(key, Util.null2String(rs3.getString(key)));
                        }
                        fnainvoiceledgerJo.put("airInvoice", airInvoiceJo);
                    }

                    rs3.executeQuery("select * from airDtlInvoice where mainid=?", id);
                    JSONArray airDtlInvoiceJa = new JSONArray();
                    while (rs3.next()) {
                        JSONObject airDtlInvoiceJo = new JSONObject();
                        for (int i = 0; i < airDtlInvoice.length; i++) {
                            String key = airDtlInvoice[i];
                            airDtlInvoiceJo.put(key, Util.null2String(rs3.getString(key)));
                        }
                        airDtlInvoiceJa.add(airDtlInvoiceJo);
                    }
                    fnainvoiceledgerJo.put("airDtlInvoice", airDtlInvoiceJa);
                } else if (invoiceType == 13) {//国际小票
                    rs3.executeQuery("select * from smallInvoice where mainid=?", id);
                    if (rs3.next()) {
                        JSONObject smallInvoiceJo = new JSONObject();
                        for (int i = 0; i < smallInvoice.length; i++) {
                            String key = smallInvoice[i];
                            smallInvoiceJo.put(key, Util.null2String(rs3.getString(key)));
                        }
                        fnainvoiceledgerJo.put("smallInvoice", smallInvoiceJo);
                    }
                } else if (invoiceType == 22) {//滴滴出行行程单
                    rs3.executeQuery("select * from fnaDidiInvoice where mainid=?", id);
                    if (rs3.next()) {
                        JSONObject fnaDidiInvoiceJo = new JSONObject();
                        for (int i = 0; i < fnaDidiInvoice.length; i++) {
                            String key = fnaDidiInvoice[i];
                            fnaDidiInvoiceJo.put(key, Util.null2String(rs3.getString(key)));
                        }
                        fnainvoiceledgerJo.put("fnaDidiInvoice", fnaDidiInvoice);
                    }

                    rs3.executeQuery("select * from fnaDidiDtlInvoice where mainid=?", id);
                    JSONArray fnaDidiDtlInvoiceJa = new JSONArray();
                    while (rs3.next()) {
                        JSONObject fnaDidiDtlInvoiceJo = new JSONObject();
                        for (int i = 0; i < fnaDidiDtlInvoice.length; i++) {
                            String key = fnaDidiDtlInvoice[i];
                            fnaDidiDtlInvoiceJo.put(key, Util.null2String(rs3.getString(key)));
                        }
                        fnaDidiDtlInvoiceJa.add(fnaDidiDtlInvoiceJo);
                    }
                    fnainvoiceledgerJo.put("fnaDidiDtlInvoice", fnaDidiDtlInvoiceJa);
                } else if (invoiceType == 23) {//船票
                    rs3.executeQuery("select * from fnaBoatInvoice where mainid=?", id);
                    if (rs3.next()) {
                        JSONObject fnaBoatInvoiceJo = new JSONObject();
                        for (int i = 0; i < fnaBoatInvoice.length; i++) {
                            String key = fnaBoatInvoice[i];
                            fnaBoatInvoiceJo.put(key, Util.null2String(rs3.getString(key)));
                        }
                        fnainvoiceledgerJo.put("fnaBoatInvoice", fnaBoatInvoiceJo);
                    }
                }

                JSONArray fnaInvoiceReimbursementJa = new JSONArray();
                rs3.executeQuery("select * from fnaInvoiceReimbursement where mainid=?", id);
                while (rs3.next()) {
                    int requestid3 = Util.getIntValue(rs3.getString("requestId"),0);
                    JSONObject fnaInvoiceReimbursementJo = new JSONObject();
                    for (int i = 0; i < fnaInvoiceReimbursement.length; i++) {
                        String key = fnaInvoiceReimbursement[i];
                        if("requestName".equals(key)){
                            String requestName="";
                            if(requestid3>0){
                                rs4.executeQuery("select  requestName from workflow_requestBase where requestId=?",requestid3);
                                if(rs4.next()){
                                    requestName = Util.null2String(rs4.getString("requestName"));
                                }
                            }
                            fnaInvoiceReimbursementJo.put("requestName",requestName);
                        }else{
                            fnaInvoiceReimbursementJo.put(key, Util.null2String(rs3.getString(key)));
                        }

                    }
                    fnaInvoiceReimbursementJa.add(fnaInvoiceReimbursementJo);
                }
                fnainvoiceledgerJo.put("fnaInvoiceReimbursement", fnaInvoiceReimbursementJa);
                invoiceArray.add(fnainvoiceledgerJo);
                page_size--;
            }
            start++;

        }
        return invoiceArray;
    }

    /**
     * 实时同步更新发票信息
     * @param infoJson
     * @return cloudId和id
     */
    public static JSONObject updateInvoiceInfo(JSONObject infoJson,String ipAdress) throws Exception {
        JSONObject jsonObject = new JSONObject();

        String fnainvoiceledger[] = {"billingDate","invoiceCode","invoiceNumber","invoiceType","seller","purchaser","invoiceServiceYype",
                "priceWithoutTax","taxRate","tax","taxIncludedPrice","authenticity","userid_new",//"reimbursementDate","reimbursePerson","requestId" 报销信息无需从发票云获取
                "invoiceSource_new","checkcode","status","card_id_new","encrypt_code_new","openid_new","wechatstatus","imageID","purchaserTaxNo","salesTaxNo",
                "entryTime","company_seal","form_type","form_name","kind","category","imageDocId","checkStatus","updateOperate","cloudId","codeConfirm","numberConfirm",
                "receiptor","reviewer","issuer","province","city","travel_tax"};
        String fnainvoiceledgerdetail[]={"invoiceserviceyype","specification","unit","unitNumber2","originalUnitPrice","priceWithoutTax","taxRate","tax","startDate","endDate","numberPlate","type"};
        String fnaInvoiceLedgerDtl[]={"remark","checkCodeSix","sellerAddress","purchaserAddress","salesBank","purchaserBank"};
        String trainInvoice[]={"time","name","station_geton","station_getoff","train_number","seat"};
        String taxiInvoice[]={"time_geton","time_getoff","mileage","place"};
        String machineInvoice[]={"time","category","seller_tax_id","buyer_tax_id"};
        String tollInvoice[]={"time","entrance","export"};
        String carInvoice[]={"time","station_geton","station_getoff","name"};
        String second_carInvoice[]={"seller_id","buyer_id","company_name","company_tax_id","license_plate","registration_number","car_code","car_model"};
        String motor_VehicleInvoice[]={"machine_code","machine_number","pretax_amount","seller_tax_id","buyer_id","tax_authorities","tax_authorities_code",
                "car_code","car_engine_code","car_model","certificate_number"};
        String airInvoice[]={"user_name","user_id","agentcode","issue_by","fare","fuel_surcharge","caac_development_fund","insurance"};
        String airDtlInvoice[]={"from_city","to_city","flight_number","airdate","airtime","seat","carrier"};
        String smallInvoice[]={"storename","time","tips","currency_code","type","discount"};

        String fnaDidiInvoice[]={"startDate","endDate","phone"};
        String fnaDidiDtlInvoice[]={"carType","time_geton","city","station_geton","station_getoff","mileage","total"};
        String fnaBoatInvoice[]={"time","station_geton","station_getoff","name","currency_code"};

        String formatDoubleColumn="priceWithoutTax,taxRate,tax,taxIncludedPrice,mileage,pretax_amount,travel_tax,total";//需要格式化金额的列，用逗号隔开
        List<String> formatDoubleList = Arrays.asList(formatDoubleColumn.split(","));

        String formatIntColumn="invoiceType,authenticity,reimbursePerson,requestId,userid_new,invoiceSource_new," +
                "status,imageID,company_seal,imageDocId,checkStatus,updateOperate";
        List<String> formatIntList = Arrays.asList(formatIntColumn.split(","));

        int id = Util.getIntValue(infoJson.getString("id"),0);


        String cloudId= Util.null2String(infoJson.getString("cloudId"));
        int invoiceType = Util.getIntValue(infoJson.getString("invoiceType"),0);
        int userid_new = Util.getIntValue(infoJson.getString("userid_new"),0);
        String invoiceNumber= Util.null2String(infoJson.getString("invoiceNumber"));
        String invoiceCode= Util.null2String(infoJson.getString("invoiceCode"));
        RecordSet rs = new RecordSet();
        List<String>valueList =new ArrayList<String>();

        //脏数据优化
        if(id==0){
            rs.executeQuery("select id from fnainvoiceLedger where invoicenumber=? and invoiceCode=?",invoiceNumber,invoiceCode);
            if(rs.next()){
                id = Util.getIntValue(rs.getString("id"),0);
            }
        }else{
            //判断该id在台账中是否存在
            int cnt = 0;
            rs.executeQuery("select count(id) cnt from fnainvoiceLedger where id=?",id);
            if(rs.next()){
                cnt= Util.getIntValue(rs.getString("cnt"),0);
            }
            if(cnt==0){
                id=0;
            }
        }
        synchronized(InvoiceCloudUtil.class) {
            //插入日志1
            FnaLogSqlUtil fnaLogSqlUtil = new FnaLogSqlUtil();
            Map<String, String> labelIdMap = new HashMap<String, String>();
            Map<String, String> beforeMap = new HashMap<String, String>();
            String opType="0";
            if(id>0){
                opType="2";
                beforeMap = fnaLogSqlUtil.getInvoiceMap(String.valueOf(id),labelIdMap);
            }

            //修改主表数据 fnainvoiceledger
            String sql = getsqlByColumn(id, fnainvoiceledger, infoJson, valueList, formatDoubleList,formatIntList,"fnainvoiceledger");
            rs.executeUpdate(sql,valueList);
            if(id<=0){
                rs.executeQuery("select id from fnainvoiceledger where cloudId=?",cloudId);
                if(rs.next()){
                    id = Util.getIntValue(rs.getString("id"));
                }
            }


            //修改明细表数据 fnainvoiceledgerdetail
            rs.executeUpdate("delete from fnainvoiceledgerdetail where mainid=?", id);
            if (infoJson.containsKey("fnainvoiceledgerdetail")) {
                String fnainvoiceledgerdetailStr = infoJson.getString("fnainvoiceledgerdetail");
                if (fnainvoiceledgerdetailStr != null && !"".equals(fnainvoiceledgerdetailStr)) {
                    JSONArray infoJsonArray = infoJson.getJSONArray("fnainvoiceledgerdetail");
                    for (int i = 0; i < infoJsonArray.size(); i++) {
                        JSONObject infoJsonDtl = infoJsonArray.getJSONObject(i);
                        if (infoJsonDtl != null && infoJsonDtl.size() > 0) {
                            sql = getsqlByColumn(id, fnainvoiceledgerdetail, infoJsonDtl, valueList, formatDoubleList, formatIntList, "fnainvoiceledgerdetail");
                            rs.executeUpdate(sql, valueList);
                        }
                    }
                }

            }

            if (invoiceType == 1 || invoiceType == 2 || invoiceType == 15 || invoiceType == 16 || invoiceType == 12
                    || invoiceType == 3 || invoiceType == 17 || invoiceType == 19 || invoiceType == 20 || invoiceType == 21) {
                //修改明细表数据 fnaInvoiceLedgerDtl
                rs.executeUpdate("delete from fnaInvoiceLedgerDtl where mainid=?", id);
                if (infoJson.containsKey("fnaInvoiceLedgerDtl")) {
                    JSONObject infoJsonDtl = infoJson.getJSONObject("fnaInvoiceLedgerDtl");
                    if (infoJsonDtl != null && infoJsonDtl.size() > 0) {
                        sql = getsqlByColumn(id, fnaInvoiceLedgerDtl, infoJsonDtl, valueList, formatDoubleList, formatIntList, "fnaInvoiceLedgerDtl");
                        rs.executeUpdate(sql, valueList);
                    }
                }
            }
            if (invoiceType == 8) {//火车票
                //修改明细表数据 trainInvoice
                rs.executeUpdate("delete from trainInvoice where mainid=?", id);
                if (infoJson.containsKey("trainInvoice")) {
                    JSONObject infoJsonDtl = infoJson.getJSONObject("trainInvoice");
                    if (infoJsonDtl != null && infoJsonDtl.size() > 0) {
                        sql = getsqlByColumn(id, trainInvoice, infoJsonDtl, valueList, formatDoubleList, formatIntList, "trainInvoice");
                        rs.executeUpdate(sql, valueList);
                    }
                }
            } else if (invoiceType == 7) {//出租车发票
                //修改明细表数据 taxiInvoice
                rs.executeUpdate("delete from taxiInvoice where mainid=?", id);
                if (infoJson.containsKey("taxiInvoice")) {
                    JSONObject infoJsonDtl = infoJson.getJSONObject("taxiInvoice");
                    if (infoJsonDtl != null && infoJsonDtl.size() > 0) {
                        sql = getsqlByColumn(id, taxiInvoice, infoJsonDtl, valueList, formatDoubleList, formatIntList, "taxiInvoice");
                        rs.executeUpdate(sql, valueList);
                    }
                }
            } else if (invoiceType == 3) {//通用机打发票
                //修改明细表数据 machineInvoice
                rs.executeUpdate("delete from machineInvoice where mainid=?", id);
                if (infoJson.containsKey("machineInvoice")) {
                    JSONObject infoJsonDtl = infoJson.getJSONObject("machineInvoice");
                    if (infoJsonDtl != null && infoJsonDtl.size() > 0) {
                        sql = getsqlByColumn(id, machineInvoice, infoJsonDtl, valueList, formatDoubleList, formatIntList, "machineInvoice");
                        rs.executeUpdate(sql, valueList);
                    }
                }
            } else if (invoiceType == 9) {//过路费发票表
                //修改明细表数据 tollInvoice
                rs.executeUpdate("delete from tollInvoice where mainid=?", id);
                if (infoJson.containsKey("tollInvoice")) {
                    JSONObject infoJsonDtl = infoJson.getJSONObject("tollInvoice");
                    if (infoJsonDtl != null && infoJsonDtl.size() > 0) {
                        sql = getsqlByColumn(id, tollInvoice, infoJsonDtl, valueList, formatDoubleList, formatIntList, "tollInvoice");
                        rs.executeUpdate(sql, valueList);
                    }
                }
            } else if (invoiceType == 10) {//客运汽车发票
                //修改明细表数据 carInvoice
                rs.executeUpdate("delete from carInvoice where mainid=?", id);
                if (infoJson.containsKey("carInvoice")) {
                    JSONObject infoJsonDtl = infoJson.getJSONObject("carInvoice");
                    if (infoJsonDtl != null && infoJsonDtl.size() > 0) {
                        sql = getsqlByColumn(id, carInvoice, infoJsonDtl, valueList, formatDoubleList, formatIntList, "carInvoice");
                        rs.executeUpdate(sql, valueList);
                    }
                }
            } else if (invoiceType == 11) {//二手车销售统一发票表
                //修改明细表数据 second_carInvoice
                rs.executeUpdate("delete from second_carInvoice where mainid=?", id);
                if (infoJson.containsKey("second_carInvoice")) {
                    JSONObject infoJsonDtl = infoJson.getJSONObject("second_carInvoice");
                    if (infoJsonDtl != null && infoJsonDtl.size() > 0) {
                        sql = getsqlByColumn(id, second_carInvoice, infoJsonDtl, valueList, formatDoubleList, formatIntList, "second_carInvoice");
                        rs.executeUpdate(sql, valueList);
                    }
                }
            } else if (invoiceType == 12) {//机动车销售统一发票
                //修改明细表数据 motor_VehicleInvoice
                rs.executeUpdate("delete from motor_VehicleInvoice where mainid=?", id);
                if (infoJson.containsKey("motor_VehicleInvoice")) {
                    JSONObject infoJsonDtl = infoJson.getJSONObject("motor_VehicleInvoice");
                    if (infoJsonDtl != null && infoJsonDtl.size() > 0) {
                        sql = getsqlByColumn(id, motor_VehicleInvoice, infoJsonDtl, valueList, formatDoubleList, formatIntList, "motor_VehicleInvoice");
                        rs.executeUpdate(sql, valueList);
                    }
                }
            } else if (invoiceType == 14) {//航空运输电子客票行程单
                //修改明细表数据 airInvoice
                rs.executeUpdate("delete from airInvoice where mainid=?", id);
                if (infoJson.containsKey("airInvoice")) {
                    JSONObject infoJsonDtl = infoJson.getJSONObject("airInvoice");
                    if (infoJsonDtl != null && infoJsonDtl.size() > 0) {
                        sql = getsqlByColumn(id, airInvoice, infoJsonDtl, valueList, formatDoubleList, formatIntList, "airInvoice");
                        rs.executeUpdate(sql, valueList);
                    }
                }
                rs.executeUpdate("delete from airDtlInvoice where mainid=?", id);
                if (infoJson.containsKey("airDtlInvoice")) {
                    String airDtlInvoiceStr = infoJson.getString("airDtlInvoice");
                    if (airDtlInvoiceStr != null && !"".equals(airDtlInvoiceStr)) {
                        JSONArray infoJsonArray = infoJson.getJSONArray("airDtlInvoice");
                        for (int i = 0; i < infoJsonArray.size(); i++) {
                            JSONObject infoJsonDtl = infoJsonArray.getJSONObject(i);
                            if (infoJsonDtl != null && infoJsonDtl.size() > 0) {
                                sql = getsqlByColumn(id, airDtlInvoice, infoJsonDtl, valueList, formatDoubleList, formatIntList, "airDtlInvoice");
                                rs.executeUpdate(sql, valueList);
                            }
                        }
                    }
                }
            } else if (invoiceType == 13) {//国际小票
                //修改明细表数据 smallInvoice
                rs.executeUpdate("delete from smallInvoice where mainid=?", id);
                if (infoJson.containsKey("smallInvoice")) {
                    JSONObject infoJsonDtl = infoJson.getJSONObject("smallInvoice");
                    if (infoJsonDtl != null && infoJsonDtl.size() > 0) {
                        sql = getsqlByColumn(id, smallInvoice, infoJsonDtl, valueList, formatDoubleList, formatIntList, "smallInvoice");
                        rs.executeUpdate(sql, valueList);
                    }
                }
            } else if (invoiceType == 22) {//船票
                //修改明细表数据 fnaBoatInvoice
                rs.executeUpdate("delete from fnaBoatInvoice where mainid=?", id);
                if (infoJson.containsKey("fnaBoatInvoice")) {
                    JSONObject infoJsonDtl = infoJson.getJSONObject("fnaBoatInvoice");
                    if (infoJsonDtl != null && infoJsonDtl.size() > 0) {
                        sql = getsqlByColumn(id, fnaBoatInvoice, infoJsonDtl, valueList, formatDoubleList, formatIntList, "fnaBoatInvoice");
                        rs.executeUpdate(sql, valueList);
                    }
                }
            } else if (invoiceType == 23) {//滴滴出行行程单
                //修改明细表数据 fnaDidiInvoice
                rs.executeUpdate("delete from fnaDidiInvoice where mainid=?", id);
                if (infoJson.containsKey("fnaDidiInvoice")) {
                    JSONObject infoJsonDtl = infoJson.getJSONObject("fnaDidiInvoice");
                    if (infoJsonDtl != null && infoJsonDtl.size() > 0) {
                        sql = getsqlByColumn(id, fnaDidiInvoice, infoJsonDtl, valueList, formatDoubleList, formatIntList, "fnaDidiInvoice");
                        rs.executeUpdate(sql, valueList);
                    }
                }
                rs.executeUpdate("delete from fnaDidiDtlInvoice where mainid=?", id);
                if (infoJson.containsKey("fnaDidiDtlInvoice")) {
                    String fnaDidiDtlInvoiceStr = infoJson.getString("fnaDidiDtlInvoice");
                    if (fnaDidiDtlInvoiceStr != null && !"".equals(fnaDidiDtlInvoiceStr)) {
                        JSONArray infoJsonArray = infoJson.getJSONArray("fnaDidiDtlInvoice");
                        for (int i = 0; i < infoJsonArray.size(); i++) {
                            JSONObject infoJsonDtl = infoJsonArray.getJSONObject(i);
                            if (infoJsonDtl != null && infoJsonDtl.size() > 0) {
                                sql = getsqlByColumn(id, fnaDidiDtlInvoice, infoJsonDtl, valueList, formatDoubleList, formatIntList, "fnaDidiDtlInvoice");
                                rs.executeUpdate(sql, valueList);
                            }
                        }
                    }

                }
            }


            //插入日志2
            Map<String, String> afterMap = fnaLogSqlUtil.getInvoiceMap(String.valueOf(id), labelIdMap);
            fnaLogSqlUtil.invoiceLedgerAddlog(new User(1), ipAdress, opType, String.valueOf(id), "2",
                    beforeMap, afterMap, labelIdMap);
        }
        jsonObject.put("id",String.valueOf(id));
        jsonObject.put("cloudId",cloudId);
        return jsonObject;
    }

    /**
     * 通过数据库字段获取sql
     * @return
     */
    public static String getsqlByColumn(int id,String tableNameArray[] ,JSONObject infoJson,List<String>valueList,
                                        List<String> formatDoubleList,List<String> formatIntList,String tableName){
        DecimalFormat df = new DecimalFormat("###############################0.00");
        StringBuffer sql=new StringBuffer();
        StringBuffer sqlPlaceHolder=new StringBuffer();
        valueList.clear();
        if(id<=0 || !"fnainvoiceledger".equals(tableName)){
            sql.append("insert into ").append(tableName).append("(");
            sqlPlaceHolder.append(" values(");
            if(!"fnainvoiceledger".equals(tableName)){//明细表，插入mainid
                sql.append("mainid,");
                sqlPlaceHolder.append("?,");
                valueList.add(String.valueOf(id));
            }
            for(int i=0;i<tableNameArray.length;i++){
                String column=tableNameArray[i];
                sql.append(column);
                sqlPlaceHolder.append("?");
                if(i!=(tableNameArray.length-1)){
                    sql.append(",");
                    sqlPlaceHolder.append(",");
                }else{
                    sql.append(")");
                    sqlPlaceHolder.append(")");
                }
                if(formatDoubleList.contains(column)) {
                    valueList.add(df.format(Util.getDoubleValue(getString(infoJson,column), 0.00)));
                }else if(formatIntList.contains(column)){
                    valueList.add(Util.null2String(Util.getIntValue(getString(infoJson,column),0)));
                }else{
                    valueList.add(getString(infoJson,column));
                }
            }
        }else{
            sql.append("update ").append(tableName).append(" set ");
            for(int i=0;i<tableNameArray.length;i++){
                String column=tableNameArray[i];
                sql.append(" ").append(column).append("=?");
                if(i!=(tableNameArray.length-1)){
                    sql.append(",");
                }
                if(formatDoubleList.contains(column)){
                    valueList.add(df.format(Util.getDoubleValue(getString(infoJson,column),0.00)));
                }else if(formatIntList.contains(column)){
                    valueList.add(Util.null2String(Util.getIntValue(getString(infoJson,column),0)));
                }else{
                    valueList.add(getString(infoJson,column));
                }
            }
            sql.append(" where id=?");
            valueList.add(String.valueOf(id));
            }
        return sql.toString()+sqlPlaceHolder.toString();
    }




    /**
     * TODO 把字节数组保存为一个文件
     *
     * @param imageBytes
     * @param filePath
     * @return
     */
    public static File getFileFromBytes(byte[] imageBytes, String filePath) {
        BufferedOutputStream stream = null;
        File file = null;
        try {
            file = new File(filePath);
            file.mkdirs();
            if (file.exists()) {
                file.delete();
                file.createNewFile();
            } else {
                file.createNewFile();
            }
            FileOutputStream fstream = new FileOutputStream(file);
            stream = new BufferedOutputStream(fstream);
            stream.write(imageBytes);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (stream != null) {
                try {
                    stream.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
        return file;
    }

    public static String getImageId(byte[] imageBytes, String cid, String tokenUrl,String uploadUrl,User user, String userName, String password) throws Exception {

        //获取token
        JSONObject tokenJson = getCloudToken(user,cid,password,userName,tokenUrl);
        String token = "";
        if(tokenJson.getBoolean("flag")){
            token = tokenJson.getString("token");
        }else{
            throw new Exception(tokenJson.getString("msg"));
        }
        uploadUrl = uploadUrl+"?token="+token;
        String imageId = "";

        //获取图片路径
        String filePath = GCONST.getRootPath() +
                "WEB-INF" + File.separatorChar +
                "fna" + File.separatorChar +
                "fpyOCRImageTemp" + File.separatorChar +
                FnaCommon.getPrimaryKeyGuid1();
        File imageFile = getFileFromBytes(imageBytes, filePath);


        try {
            //插入日志表fnaInvoiceCloudLog
            RecordSet rs = new RecordSet();
            String uuid = FnaCommon.getPrimaryKeyGuid1();
            rs.executeUpdate("insert into fnaInvoiceCloudLog(uuid,enterTime,requestType,description,interfaceurl,userName,password) values(?,?,?,?,?,?,?)",
                    uuid, Util.date(2), "OA发送请求", "发票识别-发票云-上传文件", uploadUrl, userName, password);
            FnaCommon.updateDbClobOrTextFieldValue("fnaInvoiceCloudLog", "param", "", "uuid", uuid, "string");
            FnaCommon.updateDbClobOrTextFieldValue("fnaInvoiceCloudLog", "md5Content", "", "uuid", uuid, "string");

            JSONObject data = uploadPicture(imageFile, uploadUrl);
            FnaCommon.updateDbClobOrTextFieldValue("fnaInvoiceCloudLog", "returnResult", data.toString(), "uuid", uuid, "string");
            new BaseBean().writeLog("--------fnaLog--------发票云-文件上传返回data：" + data);
            if(data.getString("status").equals("0")){
                JSONObject json = data.getJSONObject("returnInfo");
                JSONObject actionMsgJson = json.getJSONObject("actionMsg");
                if (!"0".equals(actionMsgJson.getString("code"))) {
                    throw new Exception(actionMsgJson.getString("message"));
                }

                JSONObject dataJson = json.getJSONObject("data");
                imageId = Util.null2String(dataJson.getString("id"));
            }

        } finally {
            //识别完成，删掉临时图片文件
            File tempImagefile = new File(filePath);
            if (tempImagefile.exists()) {
                tempImagefile.delete();
            }
        }

        return imageId;
    }

    /**
     * 发票云OCR
     *
     * @param cid
     * @param checkUrl
     * @param user
     * @return
     */
    public static JSONObject invoiceOCR(byte[] imageBytes, String cid, String ocrUrl,String tokenUrl,String uploadUrl, User user, String userName, String password) throws Exception {
        DecimalFormat df = new DecimalFormat("############################0.00");
        JSONObject resultJsonObj = new JSONObject();

        //1.先上传图片获取图片id
        String imageId = getImageId(imageBytes,cid,tokenUrl,uploadUrl,user, userName, password);

        //2.调用发票识别接口
        //传入的参数
        JSONObject param = new JSONObject();
        param.put("cid", cid);
        param.put("userId", user.getUID());
        param.put("image_index", imageId);
        param.put("operate_type", "1");
        param.put("is_save", "1");

        //通信
        String content = invoiceCloudEncode(param.toString(), password);
        Map<String, String> map = new HashMap<String, String>();
        map.put("appkey", userName);

        //插入日志表fnaInvoiceCloudLog
        RecordSet rs = new RecordSet();
        String uuid = FnaCommon.getPrimaryKeyGuid1();
        rs.executeUpdate("insert into fnaInvoiceCloudLog(uuid,enterTime,requestType,description,interfaceurl,userName,password) values(?,?,?,?,?,?,?)",
                uuid, Util.date(2), "OA发送请求", "发票识别-发票云", ocrUrl, userName, password);
        FnaCommon.updateDbClobOrTextFieldValue("fnaInvoiceCloudLog", "param", param.toString(), "uuid", uuid, "string");
        FnaCommon.updateDbClobOrTextFieldValue("fnaInvoiceCloudLog", "md5Content", content, "uuid", uuid, "string");

        String data = postToUrl(ocrUrl, content, map, "", uuid, "check", user,"");
        new BaseBean().writeLog("--------fnaLog--------发票云返回data：" + data);
        JSONObject dataJson = JSONObject.fromObject(data);

        //解析报文开始
        JSONObject dataJsonObj = new JSONObject();       //封装的接口返回标准信息
        JSONArray identify_results = new JSONArray();       //识别结果数据

        JSONArray infoArrayJson = dataJson.getJSONArray("infos");
        int infoArrayJson_len = infoArrayJson.size();
        for (int i = 0; i < infoArrayJson_len; i++) {
            JSONObject infoArrayJsonElt = infoArrayJson.getJSONObject(i);

            String ret = infoArrayJsonElt.getString("ret");
            if ("0".equals(ret)) {
                //获取发票云相关信息对象
                JSONObject infoJson = infoArrayJsonElt.getJSONObject("info");
                JSONObject modify_infoJson = infoJson.getJSONObject("modify_info");
                JSONObject comm_infoJson = infoJson.getJSONObject("comm_info");
                JSONObject proJson = comm_infoJson.getJSONObject("pro");
                JSONObject priceJson = comm_infoJson.getJSONObject("price");
                JSONObject buyerJson = comm_infoJson.getJSONObject("buyer");
                JSONObject payerJson = comm_infoJson.getJSONObject("payer");

                //不常用信息
                String ext = infoJson.getString("ext");
                JSONObject extJson = JSONObject.fromObject(ext);


                //转化为标准的结构
                JSONObject identifyObj = new JSONObject();
                JSONObject detailsObj = new JSONObject();
                String type = proJson.getString("type");

                String standardType =Constants.STANDARDTYPE.get(type);
                if ("".equals(standardType)) {
                    //识别失败
                    resultJsonObj.put("result", 0);
                    resultJsonObj.put("message", "发票识别失败！");
                    return resultJsonObj;
                }
                identifyObj.put("type", standardType);
                identifyObj.put("orientation", "");
                identifyObj.put("region", infoJson.getString("region"));
                if ("1".equals(type) || "2".equals(type) || "3".equals(type) || "4".equals(type) || "5".equals(type) || "22".equals(type) || "28".equals(type) ) {     //增值税
                //if ("1".equals(type) || "2".equals(type) || "3".equals(type) || "5".equals(type)) {     //增值税

                    detailsObj.put("code", getString(infoJson, "code"));
                    detailsObj.put("number", getString(infoJson, "number"));
                    detailsObj.put("date", getString(proJson, "date"));
                    detailsObj.put("pretax_amount", getString(priceJson, "amount"));
                    detailsObj.put("total", getString(priceJson, "total"));
                    detailsObj.put("tax", getString(extJson, "ttax"));
                    detailsObj.put("check_code", getString(proJson, "chcode"));
                    detailsObj.put("seller", getString(payerJson, "company"));
                    detailsObj.put("seller_tax_id", getString(payerJson, "tcode"));
                    detailsObj.put("buyer", getString(buyerJson, "company"));
                    detailsObj.put("buyer_tax_id", getString(buyerJson, "tcode"));
                    detailsObj.put("company_seal", getString(extJson, "corp_seal"));
                    detailsObj.put("form_type", getString(extJson, "form_type"));
                    detailsObj.put("form_name", getString(extJson, "form_name"));
                    detailsObj.put("kind", getString(proJson, "kind"));
                    detailsObj.put("ciphertext", getString(extJson, "ciphertext"));
                    detailsObj.put("transit_mark", getString(extJson, "transit"));
                    detailsObj.put("oil_mark", getString(extJson, "oil_mark"));
                    detailsObj.put("machine_code", getString(extJson, "machine_code"));
                    detailsObj.put("travel_tax", getString(extJson, "travel_tax"));
                    detailsObj.put("receiptor", getString(extJson, "receiptor"));
                    detailsObj.put("reviewer", getString(extJson, "reviewer"));
                    detailsObj.put("issuer", getString(extJson, "issuer"));
                    detailsObj.put("province", getString(extJson, "province"));
                    detailsObj.put("city", getString(extJson, "city"));
                    detailsObj.put("service_name", getString(extJson, "service_name"));
                    detailsObj.put("remark", getString(extJson, "comment"));

                    detailsObj.put("code_confirm", getString(extJson, "code_confirm"));
                    detailsObj.put("number_confirm", getString(extJson, "number_confirm"));

                    String item_names = "";
                    if(extJson.containsKey("products")) {
                        JSONArray productsArrayJson = extJson.getJSONArray("products");
                        for (int j = 0; j < productsArrayJson.size(); j++) {
                            if (!"".equals(item_names)) {
                                item_names += ",";
                            }
                            item_names += productsArrayJson.getJSONObject(j).get("name");
                        }
                    }
                    detailsObj.put("item_names", item_names);
                    detailsObj.put("agent_mark", getString(extJson, "agent_mark"));
                    detailsObj.put("acquisition_mark", getString(extJson, "acquisition"));
                    detailsObj.put("block_chain", getString(extJson, "block_chain"));
                    if("22".equals(type)){//区块链发票
                        detailsObj.put("block_chain", "1");
                    }
                    if("5".equals(type)){//通行费
                        detailsObj.put("transit_mark", "1");
                    }

                    detailsObj.put("code_confirm", getString(extJson, "code_confirm"));
                    detailsObj.put("number_confirm", getString(extJson, "number_confirm"));




                    JSONArray items = new JSONArray();//发票明细
                    if(extJson.containsKey("products")){
                        JSONArray productsArray = extJson.getJSONArray("products");
                        for(int j=0;j<productsArray.size();j++){
                            JSONObject productJson = productsArray.getJSONObject(j);
                            String CommodityName = getString(productJson,"name");

                            String UnitPrice = getString(productJson,"price");
                            String Quantity = getString(productJson,"qty");
                            String specification = getString(productJson,"smodel");
                            String unit = getString(productJson,"muint");
                            String Amount = getString(productJson,"amount");
                            String TaxRate =  String.valueOf(Util.getDoubleValue(getString(productJson,"trate"),0.00)/100);
                            String Tax = getString(productJson,"tprice");

                            String startDate = getString(productJson,"txrqq");
                            String endDate = getString(productJson,"txrqz");
                            String numberPlate = getString(productJson,"txfCph");
                            String carType = getString(productJson,"txfLx");

                            JSONObject jsonItems = new JSONObject();
                            jsonItems.put("quantity", Quantity);
                            jsonItems.put("price", UnitPrice);
                            jsonItems.put("name", CommodityName);
                            jsonItems.put("total", Amount);
                            jsonItems.put("tax_rate", TaxRate);
                            jsonItems.put("tax", Tax);
                            jsonItems.put("specification", specification);
                            jsonItems.put("unit", unit);
                            jsonItems.put("startDate", startDate);
                            jsonItems.put("endDate", endDate);
                            jsonItems.put("numberPlate", numberPlate);
                            jsonItems.put("type", carType);

                            items.add(jsonItems);
                        }
                    }
                    detailsObj.put("items", items);
                } else if ("9".equals(type)) {      //出租车
                    detailsObj.put("code", getString(infoJson, "code"));
                    detailsObj.put("number", getString(infoJson, "number"));
                    detailsObj.put("date", getString(proJson, "date"));
                    detailsObj.put("time_geton", getString(extJson, "time_geton"));
                    detailsObj.put("time_getoff", getString(extJson, "time_getoff"));
                    detailsObj.put("mileage", getString(extJson, "mileage"));
                    detailsObj.put("fare", getString(extJson, "fare"));
                    detailsObj.put("total", getString(priceJson, "total"));
                    detailsObj.put("place", getString(extJson, "place"));
                    detailsObj.put("kind", getString(proJson, "kind"));
                    detailsObj.put("province", getString(extJson, "province"));
                    detailsObj.put("city", getString(extJson, "city"));
                    detailsObj.put("license_plate", getString(extJson, "license_plate"));
                } else if ("12".equals(type)) {      //火车票
                    detailsObj.put("number", getString(infoJson, "number"));
                    detailsObj.put("date", getString(proJson, "date"));
                    detailsObj.put("time", getString(extJson, "time"));
                    detailsObj.put("name", getString(extJson, "name"));
                    detailsObj.put("station_geton", getString(extJson, "station_geton"));
                    detailsObj.put("station_getoff", getString(extJson, "station_getoff"));
                    detailsObj.put("train_number", getString(extJson, "train_number"));
                    detailsObj.put("seat", getString(extJson, "seat"));
                    detailsObj.put("total", getString(priceJson, "total"));
                    detailsObj.put("kind", getString(proJson, "kind"));
                    detailsObj.put("serial_number", getString(extJson, "serial_number"));
                    detailsObj.put("user_id", getString(extJson, "user_id"));
                } else if ("10".equals(type)) {      //机打发票
                    detailsObj.put("code", getString(infoJson, "code"));
                    detailsObj.put("number", getString(infoJson, "number"));
                    detailsObj.put("date", getString(proJson, "date"));
                    detailsObj.put("time", getString(extJson, "time"));
                    detailsObj.put("check_code", getString(proJson, "chcode"));
                    detailsObj.put("category", getString(extJson, "category"));
                    detailsObj.put("total", getString(priceJson, "total"));
                    detailsObj.put("seller", getString(payerJson, "company"));
                    detailsObj.put("seller_tax_id", getString(payerJson, "tcode"));
                    detailsObj.put("buyer", getString(buyerJson, "company"));
                    detailsObj.put("buyer_tax_id", getString(buyerJson, "tcode"));
                    detailsObj.put("kind", getString(proJson, "kind"));
                    detailsObj.put("province", getString(extJson, "province"));
                    detailsObj.put("city", getString(extJson, "city"));
                    detailsObj.put("company_seal", getString(extJson, "companySeal"));
                } else if ("8".equals(type)) {       //定额发票
                    detailsObj.put("code", getString(infoJson, "code"));
                    detailsObj.put("number", getString(infoJson, "number"));
                    detailsObj.put("total", getString(priceJson, "total"));
                    detailsObj.put("kind", getString(proJson, "kind"));
                    detailsObj.put("province", getString(extJson, "province"));
                    detailsObj.put("city", getString(extJson, "city"));
                    detailsObj.put("company_seal", getString(extJson, "companySeal"));
                } else if ("13".equals(type)) {       //过路费
                    detailsObj.put("code", getString(infoJson, "code"));
                    detailsObj.put("number", getString(infoJson, "number"));
                    detailsObj.put("date", getString(proJson, "date"));
                    detailsObj.put("time", getString(extJson, "time"));
                    detailsObj.put("entrance", getString(extJson, "entrance"));
                    detailsObj.put("exit", getString(extJson, "exit"));
                    detailsObj.put("total", getString(priceJson, "total"));
                    detailsObj.put("kind", getString(proJson, "kind"));
                    detailsObj.put("highway_flag", getString(extJson, "highway_flag"));
                } else if ("15".equals(type)) {       //客运汽车
                    detailsObj.put("code", getString(infoJson, "code"));
                    detailsObj.put("number", getString(infoJson, "number"));
                    detailsObj.put("date", getString(proJson, "date"));
                    detailsObj.put("time", getString(extJson, "time"));
                    detailsObj.put("station_geton", getString(extJson, "station_geton"));
                    detailsObj.put("station_getoff", getString(extJson, "station_getoff"));
                    detailsObj.put("total", getString(priceJson, "total"));
                    detailsObj.put("name", getString(extJson, "name"));
                    detailsObj.put("kind", getString(proJson, "kind"));
                    detailsObj.put("user_id", getString(extJson, "user_id"));
                } else if ("16".equals(type)) {       //航空运输电子客票行程单
                    detailsObj.put("user_name", getString(extJson, "user_name"));
                    detailsObj.put("user_id", getString(extJson, "user_id"));
                    detailsObj.put("number", getString(infoJson, "number"));
                    detailsObj.put("check_code", getString(proJson, "chcode"));
                    detailsObj.put("date", getString(proJson, "date"));
                    detailsObj.put("agentcode", getString(extJson, "agentcode"));
                    detailsObj.put("issue_by", getString(extJson, "issue_by"));
                    detailsObj.put("fare", getString(extJson, "fare"));
                    detailsObj.put("tax", getString(extJson, "tax"));
                    detailsObj.put("fuel_surcharge", getString(extJson, "fuel_surcharge"));
                    detailsObj.put("caac_development_fund", getString(extJson, "caac_development_fund"));
                    detailsObj.put("insurance", getString(extJson, "insurance"));
                    detailsObj.put("total", getString(priceJson, "total"));
                    detailsObj.put("kind", getString(proJson, "kind"));
                    detailsObj.put("international_flag", getString(extJson, "international_flag"));
                    detailsObj.put("print_number", getString(extJson, "print_number"));

                    JSONArray flightsArray_ret = new JSONArray();
                    if(extJson.containsKey("flights")) {
                        JSONArray flightsJsonArray = extJson.getJSONArray("flights");
                        for (int j = 0; j < flightsJsonArray.size(); j++) {
                            JSONObject flightObject = flightsJsonArray.getJSONObject(j);

                            JSONObject flightsOject_ret = new JSONObject();
                            flightsOject_ret.put("from", getString(flightObject, "from"));
                            flightsOject_ret.put("to", getString(flightObject, "to"));
                            flightsOject_ret.put("flight_number", getString(flightObject, "flight_number"));
                            flightsOject_ret.put("date", getString(flightObject, "date"));
                            flightsOject_ret.put("time", getString(flightObject, "time"));
                            flightsOject_ret.put("seat", getString(flightObject, "seat"));
                            flightsOject_ret.put("carrier", getString(flightObject, "carrier"));
                            flightsArray_ret.add(flightsOject_ret);
                        }
                    }
                    detailsObj.put("flights", flightsArray_ret);
                } else if ("7".equals(type)) {       //二手车销售统一发票
                    detailsObj.put("code", getString(infoJson, "code"));
                    detailsObj.put("number", getString(infoJson, "number"));
                    detailsObj.put("date", getString(proJson, "date"));
                    detailsObj.put("total", getString(priceJson, "total"));
                    detailsObj.put("seller", getString(payerJson, "company"));
                    detailsObj.put("seller_tax_id", getString(payerJson, "tcode"));
                    detailsObj.put("buyer", getString(buyerJson, "company"));
                    detailsObj.put("buyer_tax_id", getString(buyerJson, "tcode"));

                    JSONObject usedVehicleJson = extJson.getJSONObject("usedVehicle");
                    detailsObj.put("company_name", getString(usedVehicleJson, "marketCompany"));
                    detailsObj.put("company_tax_id", getString(usedVehicleJson, "marketTaxCode"));
                    detailsObj.put("license_plate", getString(usedVehicleJson, "licensePlate"));
                    detailsObj.put("registration_number", getString(usedVehicleJson, "registrationNumber"));
                    detailsObj.put("car_code", getString(usedVehicleJson, "vehicleIdentificationCode"));
                    detailsObj.put("car_model", getString(usedVehicleJson, "brankNumber"));
                    detailsObj.put("kind", getString(proJson, "kind"));
                    detailsObj.put("province", getString(extJson, "province"));
                    detailsObj.put("city", getString(extJson, "city"));
                } else if ("6".equals(type)) {       //机动车销售统一发票
                    detailsObj.put("code", getString(infoJson, "code"));
                    detailsObj.put("number", getString(infoJson, "number"));
                    detailsObj.put("machine_code", "machine_code");
                    detailsObj.put("machine_number", "machine_number");
                    detailsObj.put("date", getString(proJson, "date"));
                    detailsObj.put("pretax_amount", getString(priceJson, "amount"));
                    detailsObj.put("total", getString(priceJson, "total"));
                    detailsObj.put("seller", getString(payerJson, "company"));
                    detailsObj.put("seller_tax_id", getString(payerJson, "tcode"));
                    detailsObj.put("buyer", getString(buyerJson, "company"));
                    detailsObj.put("buyer_tax_id", getString(buyerJson, "tcode"));

                    JSONObject vehicleDetailJson = extJson.getJSONObject("vehicleDetail");
                    detailsObj.put("tax_authorities", getString(vehicleDetailJson, "taxOfficeName"));
                    detailsObj.put("tax_authorities_code", getString(vehicleDetailJson, "taxOfficeCode"));
                    detailsObj.put("car_code", getString(vehicleDetailJson, "vehicleIdentificationCode"));
                    detailsObj.put("car_engine_code", getString(vehicleDetailJson, "engineCode"));
                    detailsObj.put("car_model", getString(vehicleDetailJson, "brankNumber"));
                    detailsObj.put("certificate_number", getString(vehicleDetailJson, "certificateNumber"));

                    detailsObj.put("kind", getString(proJson, "kind"));
                    detailsObj.put("province", getString(extJson, "province"));
                    detailsObj.put("city", getString(extJson, "city"));
                    detailsObj.put("tax", getString(extJson, "ttax"));
                    detailsObj.put("tax_rate", getString(extJson, "trate"));
                } else if ("17".equals(type)) {       //小票
                    detailsObj.put("store_name", getString(extJson, "store_name"));
                    detailsObj.put("date", getString(proJson, "date"));
                    detailsObj.put("time", getString(extJson, "time"));
                    detailsObj.put("subtotal", getString(priceJson, "amount"));
                    detailsObj.put("tax", getString(extJson, "tax"));
                    detailsObj.put("discount", getString(extJson, "discount"));
                    detailsObj.put("tips", getString(extJson, "tips"));
                    detailsObj.put("total", getString(priceJson, "total"));
                    detailsObj.put("currency_code", getString(proJson, "ccy"));
                    detailsObj.put("type", getString(proJson, "kind"));
                } else if ("18".equals(type)) {       //滴滴出行行程单
                    detailsObj.put("date", getString(proJson, "date"));
                    detailsObj.put("date_start", getString(extJson, "date_start"));
                    detailsObj.put("date_end", getString(extJson, "date_end"));
                    detailsObj.put("phone", getString(extJson, "phone"));
                    detailsObj.put("total", getString(priceJson, "total"));
                    detailsObj.put("kind", getString(proJson, "kind"));

                    JSONArray itemsJson_ret = new JSONArray();
                    if(extJson.containsKey("items")) {
                        JSONArray itemsJson = extJson.getJSONArray("items");
                        for (int j = 0; j < itemsJson.size(); j++) {
                            JSONObject itemJson = itemsJson.getJSONObject(j);

                            JSONObject itemJson_ret = itemsJson.getJSONObject(j);
                            itemJson_ret.put("car_type", getString(itemJson, "car_type"));
                            itemJson_ret.put("time_geton", getString(itemJson, "time_geton"));
                            itemJson_ret.put("city", getString(itemJson, "city"));
                            itemJson_ret.put("station_geton", getString(itemJson, "station_geton"));
                            itemJson_ret.put("station_getoff", getString(itemJson, "station_getoff"));
                            itemJson_ret.put("mileage", getString(itemJson, "mileage"));
                            itemJson_ret.put("total", getString(itemJson, "total"));
                            itemsJson_ret.add(itemJson_ret);
                        }
                    }
                    detailsObj.put("items", itemsJson_ret);
                } else if ("19".equals(type)) {       //完税证明
                    detailsObj.put("number", getString(infoJson, "number"));
                    detailsObj.put("total", getString(priceJson, "total"));
                    detailsObj.put("buyer", getString(buyerJson, "company"));
                    detailsObj.put("buyer_tax_id", getString(buyerJson, "tcode"));
                    detailsObj.put("date", getString(proJson, "date"));
                } else if ("14".equals(type)) {       //船票
                    detailsObj.put("code", getString(infoJson, "code"));
                    detailsObj.put("number", getString(infoJson, "number"));
                    detailsObj.put("date", getString(proJson, "date"));
                    detailsObj.put("time", getString(extJson, "time"));
                    detailsObj.put("station_geton", getString(extJson, "station_geton"));
                    detailsObj.put("station_getoff", getString(extJson, "station_getoff"));
                    detailsObj.put("total", getString(priceJson, "total"));
                    detailsObj.put("name", getString(extJson, "name"));
                    detailsObj.put("kind", getString(proJson, "kind"));
                    detailsObj.put("province", getString(extJson, "province"));
                    detailsObj.put("city", getString(extJson, "city"));
                    detailsObj.put("currency_code", getString(proJson, "ccy"));
                } else if ("11".equals(type)) {       //可报销的其他类型发票
                    detailsObj.put("code", getString(infoJson, "code"));
                    detailsObj.put("number", getString(infoJson, "number"));
                    detailsObj.put("total", getString(priceJson, "total"));
                    detailsObj.put("date", getString(proJson, "date"));
                    detailsObj.put("kind", getString(proJson, "kind"));
                }
                identifyObj.put("details", detailsObj);

                //extra
                JSONObject extraObj = new JSONObject();
                extraObj.put("check_code_candidates", "");
                extraObj.put("check_code_last_six", "");
                extraObj.put("number_order_error", "");
                extraObj.put("qrcode", "");
                extraObj.put("barcode", "");
                identifyObj.put("extra", extraObj);

                identify_results.add(identifyObj);
            } else {
                //识别失败
                resultJsonObj.put("result", 0);
                resultJsonObj.put("message", "错误码：ret=" + ret);
                return resultJsonObj;
            }
        }

        //返回数据
        dataJsonObj.put("result", 1);
        dataJsonObj.put("message", "");
        dataJsonObj.put("identify_results", identify_results);

        //extra
        JSONObject extraObj = new JSONObject();
        extraObj.put("qrcode", "");
        extraObj.put("barcode", "");
        dataJsonObj.put("extra", extraObj);

        //封装的完整标准数据
        JSONObject packageJsonObj = new JSONObject();
        packageJsonObj.put("result", 1);
        packageJsonObj.put("message", "");
        JSONObject responseJsonObj = new JSONObject();
        responseJsonObj.put("data", dataJsonObj);
        packageJsonObj.put("response", responseJsonObj);

        resultJsonObj.put("status", Constants.SUCCESS_CODE);
        resultJsonObj.put("returnInfo", packageJsonObj);
        return resultJsonObj;
    }


    /**
     * 发票云上传附件
     * @throws Exception
     */
    public static JSONObject uploadPicture(File localFile,String url) throws Exception {
        JSONObject jsonObject=new JSONObject();
        try{
            PostMethod filePost = new PostMethod(url);

            FilePart fp = new FilePart("file", localFile);
            // StringPart:普通的文本参数
            Part[] parts = {fp};
            // 对于MIME类型的请求，httpclient建议全用MulitPartRequestEntity进行包装
            MultipartRequestEntity mre = new MultipartRequestEntity(parts, filePost.getParams());
            filePost.setRequestEntity(mre);
            HttpClient client = new HttpClient();
            int status = client.executeMethod(filePost);
            if(status==200){
                String responseBodyAsString = filePost.getResponseBodyAsString();
                JSONObject returninfo = JSONObject.fromObject(responseBodyAsString);

                jsonObject.put("status", "0");
                jsonObject.put("returnInfo", returninfo);
            }else{
                throw new Exception("接口地址请求失败！");
            }

        }catch (Exception e){
            jsonObject.put("status", "1");
            jsonObject.put("msg", e.getMessage());
        }

        return jsonObject;
    }


    /**
     * 发票云查验
     * @param invoiceCode
     * @param invoiceNo
     * @param price
     * @param billingDate
     * @param crcCode
     * @param cid
     * @param checkUrl
     * @param user
     * @return
     */
    public static JSONObject autoCheckInvoice(String invoiceCode, String invoiceNo, String price, String billingDate, String crcCode,
                                              String cid, String checkUrl,User user,String userName,String password) throws Exception {
        DecimalFormat df = new DecimalFormat("############################0.00");
        JSONObject resultObj = new JSONObject();
        JSONObject param = new JSONObject();
        param.put("cid",cid);
        param.put("userId",user.getUID());

        param.put("code",invoiceCode);
        param.put("number",invoiceNo);

        billingDate = billingDate.replaceAll("-","");


        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        Date date = dateFormat.parse(billingDate);
        int  time = Math.round(date.getTime()/1000);
        param.put("date",time);
        param.put("chcode",crcCode);
        param.put("amount",price);
        param.put("total","");//机动车暂不支持
        param.put("is_save", "1");

        String content = invoiceCloudEncode(param.toString(), password);
        Map<String, String> map = new HashMap<String, String>();
        map.put("appkey", userName);

        //插入日志表fnaInvoiceCloudLog
        RecordSet rs = new RecordSet();
        String uuid = FnaCommon.getPrimaryKeyGuid1();
        rs.executeUpdate("insert into fnaInvoiceCloudLog(uuid,enterTime,requestType,description,interfaceurl,userName,password) values(?,?,?,?,?,?,?)",
                uuid, Util.date(2),"OA发送请求","发票查验",checkUrl,userName,password);
        FnaCommon.updateDbClobOrTextFieldValue("fnaInvoiceCloudLog", "param", param.toString(), "uuid", uuid, "string");
        FnaCommon.updateDbClobOrTextFieldValue("fnaInvoiceCloudLog", "md5Content",content, "uuid", uuid, "string");

        String data = postToUrl(checkUrl, content, map, "", uuid,"check",user,"");
        JSONObject dataJson = JSONObject.fromObject(data);

        //解析报文开始
        JSONObject infoJson = dataJson.getJSONObject("info");
        JSONObject comm_infoJson = infoJson.getJSONObject("comm_info");
        JSONObject proJson = comm_infoJson.getJSONObject("pro");
        JSONObject priceJson = comm_infoJson.getJSONObject("price");
        JSONObject buyerJson = comm_infoJson.getJSONObject("buyer");
        JSONObject payerJson = comm_infoJson.getJSONObject("payer");

        String ext = infoJson.getString("ext");
        JSONObject extJson = JSONObject.fromObject(ext);

        String status = getString(proJson,"status");//状态
        if("2".equals(status)){
            //记录错误信息
            FnaInvoiceCommon.saveFailLog(user.getUID(), 1, SystemEnv.getHtmlLabelName(509480, user.getLanguage()));
            throw new Exception(SystemEnv.getHtmlLabelName(509480, user.getLanguage()));
        }

        String type = getString(proJson,"type");//标题

        String title = getString(proJson,"cname");//标题
        String _taxIncludedPrice = getString(priceJson,"total");//价税合计
        String _priceWithoutTax = getString(priceJson,"amount");//不含税金额
        String _tax = getString(extJson,"ttax");
        String _invoiceNumber = getString(infoJson,"number");//发票号码
        String _invoicecode = getString(infoJson,"code");//代码
        String _checkCode = getString(proJson,"chcode");//校验码
        String _purchaser = getString(buyerJson,"company");//购买方
        String _seller = getString(payerJson,"company");//销售方
        String _purchaserTaxNo = getString(buyerJson,"tcode");//购买方纳税人识别号
        String _salesTaxNo = getString(payerJson,"tcode");//销售方纳税人识别号
        String _billingDate = getString(proJson,"date");//开票日期
        String _remark = getString(extJson,"comment");//备注信息
        String _sellerAddress = getString(extJson,"pcontact");//销售方电话、地址
        String _purchaserAddress = getString(extJson,"bcontact");//购买方电话、地址
        String _salesBank = getString(extJson,"pbank");//销售方开户行及账号
        String _purchaserBank = getString(extJson,"bbank");//购买方开户行及账号
        String _taxRate = getString(extJson,"trate");//税率
        String _invoiceServiceYype = "";//货物或应税服务类型
        JSONArray items = new JSONArray();//发票明细
        if(extJson.containsKey("products")){
            JSONArray productsArray = extJson.getJSONArray("products");
            for(int i=0;i<productsArray.size();i++){
                JSONObject productJson = productsArray.getJSONObject(i);
                String CommodityName = getString(productJson,"name");
                if("".equals(_invoiceServiceYype)) {
                    _invoiceServiceYype = CommodityName;
                }
                String UnitPrice = getString(productJson,"price");
                String Quantity = getString(productJson,"qty");
                String specification = getString(productJson,"smodel");
                String unit = getString(productJson,"muint");
                String Amount = getString(productJson,"amount");
                String TaxRate =  String.valueOf(Util.getDoubleValue(getString(productJson,"trate"),0.00)/100);
                String Tax = getString(productJson,"tprice");

                String startDate = getString(productJson,"txrqq");
                String endDate = getString(productJson,"txrqz");
                String numberPlate = getString(productJson,"txfCph");
                String carType = getString(productJson,"txfLx");

                JSONObject jsonItems = new JSONObject();
                jsonItems.put("Quantity", Quantity);
                jsonItems.put("UnitPrice", UnitPrice);
                jsonItems.put("CommodityName", CommodityName);
                jsonItems.put("Amount", Amount);
                jsonItems.put("TaxRate", TaxRate);
                jsonItems.put("Tax", Tax);
                jsonItems.put("specification", specification);
                jsonItems.put("unit", unit);

                jsonItems.put("startDate", startDate);
                jsonItems.put("endDate", endDate);
                jsonItems.put("numberPlate", numberPlate);
                jsonItems.put("type", carType);

                items.add(jsonItems);
            }
        }


        //以下代码可能某些客户版本较低，不存在
        {
            int id= 0;
            rs.executeQuery("select id from fnaInvoiceDetailInfo where invoiceNumber=? and invoiceCode=?",_invoiceNumber,_invoicecode);
            if(rs.next()){
                id = Util.getIntValue(rs.getString("id"),0);
            }
            if(id <=0){
                rs.executeUpdate("insert into fnaInvoiceDetailInfo (invoiceNumber,invoiceCode) values(?,?)",_invoiceNumber,_invoicecode);
                rs.executeQuery("select id maxid from fnaInvoiceDetailInfo where invoiceNumber=? and invoiceCode=?",_invoiceNumber,_invoicecode);
                int maxid = 0;
                if(rs.next()){
                    maxid = Util.getIntValue(rs.getString("maxid"));
                }
                FnaCommon.updateDbClobOrTextFieldValue("fnaInvoiceDetailInfo", "detailInfo", items.toString(), "id", maxid+"", "int");
            }else{
                FnaCommon.updateDbClobOrTextFieldValue("fnaInvoiceDetailInfo", "detailInfo", items.toString(), "id", id+"", "int");
            }
            FnaAbstractInterface.saveInvoiceServiceYype(items, "CommodityName");
        }

        //机动车销售统一发票特殊字段
        String machine_code=getString(extJson,"machine_code");//机打代码
        String machine_number=getString(extJson,"machine_number");//机打号码
        String tax_authorities=getString(extJson,"taxOfficeName");//主管税务机关
        String tax_authorities_code=getString(extJson,"taxOfficeCode");//主管税务机关代码
        String car_code=getString(extJson,"vehicleIdentificationCode");//车架号/车辆识别代码
        String car_engine_code=getString(extJson,"engineCode");//发动机号码
        String car_model=getString(extJson,"brankNumber");//厂牌型号
        String certificate_number=getString(extJson,"certificateNumber");//合格证号



        resultObj.put("title", title);
        resultObj.put("_taxIncludedPrice", df.format(Util.getDoubleValue(_taxIncludedPrice,0.00)));
        resultObj.put("_priceWithoutTax", df.format(Util.getDoubleValue(_priceWithoutTax,0.00)));
        resultObj.put("_tax", df.format(Util.getDoubleValue(_tax,0.00)));
        resultObj.put("_taxRate", df.format(Util.getDoubleValue(_taxRate,0.00)));
        resultObj.put("_invoiceNumber", _invoiceNumber);
        resultObj.put("_invoicecode", _invoicecode);
        resultObj.put("_purchaser", _purchaser);
        resultObj.put("_seller", _seller);
        resultObj.put("_purchaserTaxNo", _purchaserTaxNo);
        resultObj.put("_salesTaxNo", _salesTaxNo);
        resultObj.put("_billingDate", _billingDate);
        resultObj.put("_remark", _remark);
        resultObj.put("_sellerAddress", _sellerAddress);
        resultObj.put("_purchaserAddress", _purchaserAddress);
        resultObj.put("_salesBank", _salesBank);
        resultObj.put("_purchaserBank", _purchaserBank);
        resultObj.put("_checkCode", _checkCode);
        resultObj.put("_invoiceServiceYype", _invoiceServiceYype);
        resultObj.put("_invoiceType", Constants.CLOUDTOOATYPE.get(type));

        int recoginizeinvoiceType = SdkInvoiceUtil.recoginizeInvoiceType(invoiceCode);
        resultObj.put("fplx", recoginizeinvoiceType);

        //机动车销售统一发票特殊字段
        resultObj.put("_machine_code", machine_code);
        resultObj.put("_machine_number", machine_number);
        resultObj.put("_tax_authorities", tax_authorities);
        resultObj.put("_tax_authorities_code", tax_authorities_code);
        resultObj.put("_car_code", car_code);
        resultObj.put("_car_engine_code", car_engine_code);
        resultObj.put("_car_model", car_model);
        resultObj.put("_certificate_number", certificate_number);

        resultObj.put("detaildata", items);
        resultObj.put("status", "1");
        return resultObj;
    }


    /**
     * 判断是否存在生效的发票云接口-流程组用
     * @param user
     * @return
     */
    public static boolean isExistInvoiceCloudInterface(User user){
        JSONObject interfaceInfo = InvoiceCloudUtil.getInterfaceInfo(user, false, false, true);
        JSONObject cloudInfo = interfaceInfo.getJSONObject("cloud");
        boolean existEffectCloud = cloudInfo.getBoolean("existEffectCloud");
        return existEffectCloud;
    }

    /**
     * 获取cloudId(发票云id)或者inoviceId(发票台账id)
     * @param ids
     * @param method 传cloudId或inoviceId  传cloudId表示要通过inoviceId获取cloudId,  传inoviceId表示要通过cloudId获取inoviceId
     * @return 返回的ids和传的ids顺序保持一致
     */
    public static String getCloudIdOrInoviceId(String ids,String method){
        StringBuffer idsBuffer = new StringBuffer();
        RecordSet rs = new RecordSet();
        String[] idsSplit = ids.split(",");
        if("cloudId".equals(method)){
            for(int i=0;i<idsSplit.length;i++){
                rs.executeQuery("select cloudId from fnaInvoiceLedger where id=?",idsSplit[i]);
                if(rs.next()){
                    String cloudId = Util.null2String(rs.getString("cloudId"));
                    if(idsBuffer.length()==0){
                        idsBuffer.append(cloudId);
                    }else{
                        idsBuffer.append(",").append(cloudId);
                    }
                }
            }
        }else if("inoviceId".equals(method)){
            for(int i=0;i<idsSplit.length;i++){
                rs.executeQuery("select id from fnaInvoiceLedger where cloudId=?",idsSplit[i]);
                if(rs.next()){
                    String id = Util.null2String(rs.getString("id"));
                    if(idsBuffer.length()==0){
                        idsBuffer.append(id);
                    }else{
                        idsBuffer.append(",").append(id);
                    }
                }
            }
        }
        return idsBuffer.toString();
    }
	
    /**
     * @Description: 同步转移归属人/共享人信息到发票云
     * @param interfaceurl
     * @param param
     * @param userName
     * @param password
     * @return: net.sf.json.JSONObject
     * @Author: konghang
     * @Date: 10:04 2020/10/14
     */
    public static JSONObject synOwnerInfo(String interfaceurl, JSONObject param, String userName, String password) {
        JSONObject jsonObject = new JSONObject();
        try {
            String content = invoiceCloudEncode(param.toString(), password);
            Map<String, String> map = new HashMap<String, String>();
            map.put("appkey", userName);

            //插入日志表fnaInvoiceCloudLog
            RecordSet rs = new RecordSet();
            String uuid = FnaCommon.getPrimaryKeyGuid1();
            rs.executeUpdate("insert into fnaInvoiceCloudLog(uuid,enterTime,requestType,description,interfaceurl,userName,password) values(?,?,?,?,?,?,?)",
                    uuid, Util.date(2), "OA发送请求", "同步转移归属人/共享人信息到发票云", interfaceurl, userName, password);
            FnaCommon.updateDbClobOrTextFieldValue("fnaInvoiceCloudLog", "param", param.toString(), "uuid", uuid, "string");
            FnaCommon.updateDbClobOrTextFieldValue("fnaInvoiceCloudLog", "md5Content", content, "uuid", uuid, "string");

            String data = postToUrl(interfaceurl, content, map, "", uuid);
            jsonObject.put("flag", true);
            jsonObject.put("data", data);
        } catch (Exception e) {
            jsonObject.put("flag", false);
            jsonObject.put("msg", e.getMessage());
        }
        return jsonObject;
    }

    /**
     * @Description: 同步共享人信息到发票云
     * @param interfaceurl
     * @param param
     * @param userName
     * @param password
     * @return: net.sf.json.JSONObject
     * @Author: konghang
     * @Date: 10:04 2020/10/14
     */
    public static JSONObject sysSharerInfo(String interfaceurl, JSONObject param, String userName, String password) {
        JSONObject jsonObject = new JSONObject();
        try {
            String content = invoiceCloudEncode(param.toString(), password);
            Map<String, String> map = new HashMap<String, String>();
            map.put("appkey", userName);

            //插入日志表fnaInvoiceCloudLog
            RecordSet rs = new RecordSet();
            String uuid = FnaCommon.getPrimaryKeyGuid1();
            rs.executeUpdate("insert into fnaInvoiceCloudLog(uuid,enterTime,requestType,description,interfaceurl,userName,password) values(?,?,?,?,?,?,?)",
                    uuid, Util.date(2), "OA发送请求", "同步共享人信息到发票云", interfaceurl, userName, password);
            FnaCommon.updateDbClobOrTextFieldValue("fnaInvoiceCloudLog", "param", param.toString(), "uuid", uuid, "string");
            FnaCommon.updateDbClobOrTextFieldValue("fnaInvoiceCloudLog", "md5Content", content, "uuid", uuid, "string");

            String data = postToUrl(interfaceurl, content, map, "", uuid);
            jsonObject.put("flag", true);
            jsonObject.put("data", data);
        } catch (Exception e) {
            jsonObject.put("flag", false);
            jsonObject.put("msg", e.getMessage());
        }
        return jsonObject;
    }


    /**
     * 获取发票使用次数接口
     * @param cid
     * @param userId
     * @return
     */
    public static JSONObject getInvoiceUsedNumberInfo(String cid,int userId){
        JSONObject invoiceCloudUrl = InvoiceCloudUtil.getInvoiceCloudUrl();
        RecordSet rs = new RecordSet();
        String userName="";
        String password="";
        String javaUrl="";
        rs.executeQuery("select * from fnaInvoiceInterface where cid=?",cid);
        if(rs.next()){
            userName = Util.null2String(rs.getString("userName"));
            password = FnaInvoiceCommon.fnaDecrypt(Util.null2String(rs.getString("password")));
            javaUrl = Util.null2String(rs.getString("javaUrl"));
        }
        return getInvoiceUsedNumberInfo(javaUrl+"/"+invoiceCloudUrl.getString("invoiceUsedNumberInfo"),cid,userName,password,userId);
    }

    /**
     * 获取发票使用次数接口
     * @param invoiceUsedNumberInfoUrl
     * @param cid
     * @param userName
     * @param password
     * @param userId
     * @return
     */
    public static JSONObject getInvoiceUsedNumberInfo(String invoiceUsedNumberInfoUrl,String cid,String userName,String password,int userId){
        JSONObject jsonObject = new JSONObject();
        try{
            JSONObject param = new JSONObject();
            param.put("cid",cid);
            param.put("userId",userId);
            String content = invoiceCloudEncode(param.toString(), password);
            Map<String, String> map = new HashMap<String, String>();
            map.put("appkey", userName);
            //插入日志表fnaInvoiceCloudLog
            RecordSet rs = new RecordSet();
            String uuid = FnaCommon.getPrimaryKeyGuid1();
            rs.executeUpdate("insert into fnaInvoiceCloudLog(uuid,enterTime,requestType,description,interfaceurl,userName,password) values(?,?,?,?,?,?,?)",
                    uuid,Util.date(2),"OA发送请求","获取发票使用次数",invoiceUsedNumberInfoUrl,userName,password);
            FnaCommon.updateDbClobOrTextFieldValue("fnaInvoiceCloudLog", "param", param.toString(), "uuid", uuid, "string");
            FnaCommon.updateDbClobOrTextFieldValue("fnaInvoiceCloudLog", "md5Content",content, "uuid", uuid, "string");
            String data = postToUrl(invoiceUsedNumberInfoUrl, content, map, "",uuid);
            jsonObject.put("flag",true);
            jsonObject.put("data",data);
        }catch (Exception e){
            jsonObject.put("flag",false);
            jsonObject.put("msg",e.getMessage());
        }
        return jsonObject;
    }

    /**
     * 获取AES加密的key
     * @param invoiceUsedNumberInfoUrl
     * @param cid
     * @param userName
     * @param password
     * @param userId
     * @return
     */
    public static JSONObject createAesKey(String createAesKeyUrl,String password,String userName){
        JSONObject jsonObject = new JSONObject();
        try{

            String content = invoiceCloudEncode("", password);
            Map<String, String> map = new HashMap<String, String>();
            map.put("appkey", userName);
            //插入日志表fnaInvoiceCloudLog
            RecordSet rs = new RecordSet();
            String uuid = FnaCommon.getPrimaryKeyGuid1();
            rs.executeUpdate("insert into fnaInvoiceCloudLog(uuid,enterTime,requestType,description,interfaceurl,userName,password) values(?,?,?,?,?,?,?)",
                    uuid,Util.date(2),"OA发送请求","获取AES加密的key",createAesKeyUrl,userName,password);
            FnaCommon.updateDbClobOrTextFieldValue("fnaInvoiceCloudLog", "md5Content",content, "uuid", uuid, "string");
            String data = postToUrl(createAesKeyUrl, content, map, "",uuid);
            jsonObject.put("flag",true);
            jsonObject.put("data",data);
        }catch (Exception e){
            jsonObject.put("flag",false);
            jsonObject.put("msg",e.getMessage());
        }
        return jsonObject;
    }

    /**
     * 报销校验
     * @param reimburseUrl
     * @param aesKey
     * @param bodyJson
     * @param userName
     * @param password
     * @param description
     * @return
     */
    public static JSONObject reimburseInvoice(String reimburseUrl,String aesKey ,JSONObject bodyJson ,String userName,String password,String description){
        JSONObject jsonObject = new JSONObject();
        try{
            String bodyStr = InvoiceCloudAESUtil.encrypt(aesKey,bodyJson.toString());
            String content = invoiceCloudEncode(bodyStr.toString(), password);
            Map<String, String> map = new HashMap<String, String>();
            map.put("appkey", userName);

            //插入日志表fnaInvoiceCloudLog
            RecordSet rs = new RecordSet();
            String uuid = FnaCommon.getPrimaryKeyGuid1();
            rs.executeUpdate("insert into fnaInvoiceCloudLog(uuid,enterTime,requestType,description,interfaceurl,userName,password) values(?,?,?,?,?,?,?)",
                    uuid,Util.date(2),"OA发送请求",description,reimburseUrl,userName,password);
            FnaCommon.updateDbClobOrTextFieldValue("fnaInvoiceCloudLog", "param", bodyJson.toString(), "uuid", uuid, "string");
            FnaCommon.updateDbClobOrTextFieldValue("fnaInvoiceCloudLog", "md5Content",content, "uuid", uuid, "string");

            String data = postToUrl(reimburseUrl, content, map, "",uuid,aesKey);

            jsonObject.put("flag",true);
            jsonObject.put("data",data);
        }catch (Exception e){
            jsonObject.put("flag",false);
            jsonObject.put("msg",e.getMessage());
        }

        return jsonObject;
    }


    /**
     * 发票云附件上传
     * @param imageBytes
     * @param cid
     * @param ocrUrl
     * @param tokenUrl
     * @param uploadUrl
     * @param user
     * @param userName
     * @param password
     * @return
     * @throws Exception
     */
    public static JSONArray uploadFileInvoice(byte[] imageBytes, String cid, String ocrUrl,String localCheckUrl,String tokenUrl,String uploadUrl, User user, String userName, String password) throws Exception {
        JSONArray  uoloadFileArray = new JSONArray();

        //1.先上传图片获取图片id
        String imageId = getImageId(imageBytes,cid,tokenUrl,uploadUrl,user, userName, password);
        //2.识别
        JSONObject param = new JSONObject();
        param.put("cid", cid);
        param.put("userId", user.getUID());
        param.put("image_index", imageId);
        param.put("operate_type", "0");
        param.put("is_save", "0");
        String content = invoiceCloudEncode(param.toString(), password);
        Map<String, String> map = new HashMap<String, String>();
        map.put("appkey", userName);
        //插入日志表fnaInvoiceCloudLog
        RecordSet rs = new RecordSet();
        String uuid = FnaCommon.getPrimaryKeyGuid1();
        rs.executeUpdate("insert into fnaInvoiceCloudLog(uuid,enterTime,requestType,description,interfaceurl,userName,password) values(?,?,?,?,?,?,?)",
                uuid, Util.date(2), "OA发送请求", "发票识别新-发票云", ocrUrl, userName, password);
        FnaCommon.updateDbClobOrTextFieldValue("fnaInvoiceCloudLog", "param", param.toString(), "uuid", uuid, "string");
        FnaCommon.updateDbClobOrTextFieldValue("fnaInvoiceCloudLog", "md5Content", content, "uuid", uuid, "string");
        String data = postToUrl(ocrUrl, content, map, "", uuid, "check", user,"");
        JSONObject dataJson = JSONObject.fromObject(data);

        //插入调用记录日志
        JSONObject jo = new JSONObject();
        jo.put("status","0");
        jo.put("returnInfo", dataJson);
        FnaInvoiceCommon.addFnainvoiceLog("1",imageBytes,"","","","","",
                jo, user, "OCR","");

        JSONArray infoArrayJson = dataJson.getJSONArray("infos");
        String open_valid = Util.null2String(getString(dataJson,"open_valid"));
        int infoArrayJson_len = infoArrayJson.size();
        if(infoArrayJson_len==0){
            FnaInvoiceCommon.saveFailLog(user.getUID(), 0, SystemEnv.getHtmlLabelName(509482, user.getLanguage()));//识别结果为空!
            throw new Exception(SystemEnv.getHtmlLabelName(	509587,user.getLanguage()));
        }
        for (int i = 0; i < infoArrayJson_len; i++) {
            JSONObject uploadFileJson = new JSONObject();
            JSONObject infoArrayJsonElt = infoArrayJson.getJSONObject(i);
            String ret = Util.null2String(getString(infoArrayJsonElt,"ret"));
            JSONObject infoJson = infoArrayJsonElt.getJSONObject("info");
            JSONObject comm_info = infoJson.getJSONObject("comm_info");
            JSONObject pro = comm_info.getJSONObject("pro");
            String type = Util.null2String(getString(infoJson,"type"));
            String cloudId = Util.null2String(getString(infoJson,"fid"));
            String invoiceNumber = Util.null2String(getString(infoJson,"number"));
            if ("0".equals(ret)) {
                if("1".equals(open_valid) && ("1".equals(type) || "2".equals(type) || "3".equals(type) || "4".equals(type) || "5".equals(type) || "6".equals(type) || "7".equals(type))){//需要查验
                    JSONObject param1 = new JSONObject();
                    param1.put("fid", cloudId);
                    String content1 = invoiceCloudEncode(param1.toString(), password);
                    Map<String, String> map1 = new HashMap<String, String>();
                    map1.put("appkey", userName);
                    String uuid1 = FnaCommon.getPrimaryKeyGuid1();
                    rs.executeUpdate("insert into fnaInvoiceCloudLog(uuid,enterTime,requestType,description,interfaceurl,userName,password) values(?,?,?,?,?,?,?)",
                            uuid1, Util.date(2), "OA发送请求", "发票查验新-发票云", localCheckUrl, userName, password);
                    FnaCommon.updateDbClobOrTextFieldValue("fnaInvoiceCloudLog", "param", param1.toString(), "uuid", uuid1, "string");
                    FnaCommon.updateDbClobOrTextFieldValue("fnaInvoiceCloudLog", "md5Content", content1, "uuid", uuid1, "string");
                    try{
                        String data1 = postToUrl(localCheckUrl, content1, map1, "", uuid1,"check",user,"");
                        JSONObject dataJson1 = JSONObject.fromObject(data1);
                        JSONObject infoJson1 = dataJson1.getJSONObject("info");
                        JSONObject comm_infoJson = infoJson1.getJSONObject("comm_info");
                        JSONObject proJson = comm_infoJson.getJSONObject("pro");
                        String status = getString(proJson,"status");//状态
                        if("2".equals(status)){
                            //记录错误信息
                            FnaInvoiceCommon.saveFailLog(user.getUID(), 1, SystemEnv.getHtmlLabelName(509480, user.getLanguage()));
                            uploadFileJson.put("msg",invoiceNumber+":"+SystemEnv.getHtmlLabelName(509480, user.getLanguage()));
                            uploadFileJson.put("flag",false);
                        }else{
                            uploadFileJson.put("flag",true);
                        }
                    }catch (Exception e){
                        uploadFileJson.put("flag",false);
                        uploadFileJson.put("msg",invoiceNumber+":"+e.getMessage());
                    }
                }else{
                    uploadFileJson.put("flag",true);
                }
                uploadFileJson.put("cloudId",cloudId);
            }else{
                uploadFileJson.put("cloudId",cloudId);
                uploadFileJson.put("msg",Util.null2String(getString(infoArrayJsonElt,"message")));
                uploadFileJson.put("flag",true);
            }

            uoloadFileArray.add(uploadFileJson);
        }
        return uoloadFileArray;
    }
}
